Can Django be used to create a website for creating custom websites depending on the user needs? There will be more than one template and each user will have a custom url for their websites.
I don't know if this can this be achieved with Django CMS.
Sure, it is possible but it requires ton of work, because you need to write bunch of templates, or/and logic that handles templates.
You could write TemplateMixin, that depending on passed domain, or kwarg in url changes the template in the View. So, for example, it could look like that:
class TemplateMixin:
template_name = None
request = None
model = None
def get_template_names(self):
"""
Return a list of template names to be used for the request.
Must return a list. May not be called if render_to_response() is overridden.
"""
db_settings = Settings.objects.get_or_create()[0]
if self.template_name is None:
raise ImproperlyConfigured(
'TemplateResponseMixin requires either a definition of '
'\"template_name\" or an implementation of \"get_template_names()\"')
template = db_settings.website_template
ready_template = '/'.join([template, self.template_name])
return [ready_template]
There are also solutions for handling multiple domains, so you could detect what current domain is via self.request in get_template_names method. The templates are handled by prefix. The kwargs also should be in self.kwargs, so you can detect which site you need to present via custom namespace url.
You can also create WebsiteSettings model that handles various templates, and is manageable via simple custom dashboard panel, and belongs to user, or user groups. The fields that it should have is 'template' with choices attribute, relation to User (or CustomUser model), and bunch of settings you want to give a user (or you could have different model('s) for that).
The solution I bring here is simple to show the idea - but it can be insufficient, to accomplish what you really want you must write the whole mixins, views etc. logic yourself.
Related
In Django I'm trying to implement some kind of a "security middleware", which gives access to certain db information only, if the logged in user matches.
Up to now I found two approaches: middleware or custom function in manager (Both explained here Django custom managers - how do I return only objects created by the logged-in user?).
Example for cleanest solution: custom function
class UserContactManager(models.Manager):
def for_user(self, user):
return self.get_query_set().filter(creator=user)
class MyUser(models.Model):
# Managers
objects = UserContactManager()
# then use it like this in views
data = MyUser.objects.for_user(request.user)
However, this solution only works, if you have control over the code which invokes this custom function (here: for_user()).
But if you are using third parties apps like Django-REST, Graphene or AdminViews, they don't have the possibility to configure a specific query-func to use.
My goal:
Replace the default Manager
Add user-based filters to query_set
Use the model as normal in all app configurations
Idea (pseudo code!)
from django.x import current_user
class UserBasedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(author=current_user.name)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = UserBasedManager() # The default manager.
Now I could use the model Book as normal in all extensions.
I know this solution would have some drawbacks, which are okay for me:
Can be only used when user is available (e.g. no direct script support)
Handling no or anonymous user is missing (left it away to keep example short)
My use case
I have a project, which shall give access to data by different interfaces (admin pages, custom views, rest, graphql).
As I have so many interfaces, I don't want to implement the access-rights in the views. This would cost too much time and is hard to maintain and the risk for security problems in one specific view/interface is too high.
Let's say I'm storing commits of git repositories in a database.
And the user shall get access to all commits, which are part of repos the user has READ access.
The question is: How can I implement this as a generic, view/interface independent solution?
Install django-threadlocals package and call get_current_user function to get the current user
from threadlocals.threadlocals import get_current_user
class UserBasedManager(models.Manager):
def get_queryset(self):
current_user = get_current_user()
return super().get_queryset().filter(author=current_user.name)
I'm trying to create a website with multiple template for all pages.
I've created a templates folder and there are 3 folders in it. each folder contains base.html, home.html, etc.
Admin can choose each template from admin panel and in my view load template like this.
class HomeView(TemplateView):
default_template = CustomTemplate.objects.first().name
template_name = default_template + '/home.html'
The problem is I have to restart server to apply admin's changes.
Is there any way to do this without restarting server?
I've also tried to enable / disable loader cache but I guess the problem is not depends to cache system.
Anything defined directly at class level will persist for the entirety of a process.
Luckily, Django's class-based views provide a series of hooks so that you can define things on a per-request basis. In this case, the method you want is get_template_names (which returns a list of templates to search for).
So:
class HomeView(TemplateView):
def get_template_names(self):
default_template = CustomTemplate.objects.first().name
return ['{}/home.html'.format(default_template)]
I think my question is pretty clear:
I am interested in finding out some ways of using model (DB) data without creating views.
I have already created a website using djangocms and now I would like to develop a little blog.
I am aware of this project but this is not as straight forward as I'd need ( it is pretty complex for my purpose ).
For example, in the first place, I would like to know if there's any possibility to create a basic template in which I will be able to display the users(their names) directly from the database.
In Django, you basically can't get data from a model to a template without a view that puts it there. That's the whole point of views.
You don't necessarily have to create a views.py file, because there might be other mechanisms that you can make use of, such as django CMS's plugin system.
I don't understand what connection your question has to developing a weblog though.
What you can do is create a context processor which essentially is a function which returns a dictionary & it's added to every request context.
For example, I have a model which provides information for the site as a whole, like social links, a name etc. Take a look;
from django.contrib.sites.models import get_current_site
from .models import SiteSettings
def site_settings(request):
current_site = get_current_site(request)
try:
settings = SiteSettings.objects.get(site_id=current_site.id)
except SiteSettings.MultipleObjectsReturned:
settings = SiteSettings.objects.filter(
site_id=current_site.id
).order_by('id')[0]
except SiteSettings.DoesNotExist:
return {
'SITE_SITE_NAME': None,
'SITE_SHORT_NAME': None,
}
# SiteSettings object exists, so assign the attributes you want, to context
# variables returned by the context processor for all views.
data = {
'SITE_SITE_NAME': settings.site_name,
'SITE_SHORT_NAME': settings.short_name,
}
return data
So by doing that you can use things like {{ SITE_SHORT_NAME }} in any template, and this obviously makes any information you hold in a table available via one of these processors. Just make sure you create necessary DoesNotExist exceptions when doing this with models.
I'm trying to manage my REST API like that :
http://xxx/users/userid[0-9]+/projects/projectid[0-9]+/tasks/taskid[0-9]+/
So I can access the JSON easily in my website. But, the thing is, I defined my view classes using the REST framework generic views. For example, here is my UserDetail view :
class UserDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
But of course I don't want all my users to be displayed, I just want my user with the ID userid to be displayed. I don't really know how to do it, I tried
queryset = User.objects.filter(id=userid)
but of course userid is not defined... Any help please ?
Edit : just to clarify, here is the url that leads to this view :
url(r'^users/(?P<pku>[0-9]+)/$', views.UserDetail.as_view(
), name='user-detail'),
First of all, If you want to use class based views, you should read some more about them. They are thoroughly explained on Django's docs and you can read about the specific generics of the framework you're using on the REST framework docs too. I'm not saying that you haven't read those, just that you seem to be missing some basic concepts that are explained there.
Now, to the problem at hand, if you look at the doc's of the generic view you're extending, you can see that it represents the endpoints for a single instance, meaning that it won't act on all your model's instances (as you seem to assume).
Also, you can see that this view is built on top of a series of other classes, the more critical one being GenericAPIView. On there you can see two things:
The queryset class field in this context is meant for filtering the posible instances you can manipulate, not obtaining the specific instance described on your url.
The lookup_field is the field that defines which attribute from your model will be used for getting the actual instance. You should define this field to whatever field you're going to use on your url to identify your object (generally it's pk). It's also important to note that the url should include a keyword argument corresponding to this value.
Internally, the view will take care of calling the get_object method, which usese the lookup_field value to find the specific model, and then feed that object to the serializer and return the result back to the client.
DISCLAIMER: I've never used Django REST framework, I put this answer togheter by reading the relevants docs and based on my experience.
I guess you need this:
Resolve function (django 1.4)
Then in your view class method you can do:
temp1, args, kwargs = resolve(self.request.path)
I would like to allow a User to have an admin interface to their own Video objects. I was planning on writing some views that allowed things like setting attributes like "published" or deleting objects.
I've started looking into using django's Admin site - but that seems like it might be overly complicated for what I want (just deleting/ setting the published attribute).
Is one approach better than the other? Writing something from scratch or using the Admin site?
If I were to write something from scratch - what is the correct way to achieve ModelAdmin style actions (ie. delete_selected(queryset, request))
This is exactly what the admin should be used for! How could it be too complicated? Even writing a handful of lines of HTML would take longer.
If you built this yourself, no matter how simple, you'll have to define views that list objects, validate input, check permissions, write HTML, implement some kind of multiple action system that maps to python code, ....
Assuming you don't want to do that:
You're going to want to look into making multiple admin sites and filtering admin results to only those that belong to the user via overriding the queryset method on a ModelAdmin
# pasted from docs
class MyModelAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(MyModelAdmin, self).queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)