How can I use model (DB) data in djangoCMS, without creating views? - django

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.

Related

Create multiple website templates with django cms or any tool

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.

When POSTing in DRF, where to create an object and how to validate a complex JSON field efficiently?

Complete DRF beginner here... I'm confused about the following concepts:
Let's say I POST some data, including a complex JSON blob for one of the fields, in order to create an object. Where should I actually create this object? Looking at the 3.1 docs, it seems like two places are equally valid for this: Serializer.create() and ViewSet.create(). How do I decide where to create my object and which way is considered "canonical"?
I understand that I need to run Serializer.is_valid() in order to validate the POSTed data. However, what is the difference between .data and .validated_data? They appear to be the same.
Finally, what is the "canonical" way to use a JSONField (e.g. django-jsonfield, but I'm not married to this package/implementation)? I have a model with several JSONFields and would like to use it "correctly" in DRF. I am aware of https://stackoverflow.com/a/28200902/585783, but it doesn't seem enough.
EDIT: My use case is an API POST that includes a complex JSON blob in one of the fields. I need to parse the JSON field, validate it, get/create several objects based on it, link new and existing objects, and finally store the JSON field in one of the new objects. So, I need to do custom validation for this JSON field by parsing it to python:
from django.utils.six import BytesIO
from rest_framework.parsers import JSONParser
class MySerializer(serializers.ModelSerializer):
my_json_field = JSONSerializerField()
def validate_my_json_field(self, value):
stream = BytesIO(value)
list_of_dicts = JSONParser().parse(stream)
# do lots of validation to list_of_dicts
# render list_of_dicts back to a JSON string
return validated_list_of_dicts_as_json
Now, depending on which way I choose in Concept 1, I have to parse the validated JSON again to create my objects in create(), which doesn't feel right.
Thanks in advance!
The contents of HTTP requests (POST, GET, PUT, DELETE) will always be processed by the views (View, APIView, generic views, viewsets). The serializers are just part of how these views process the requests. Serializers are the "means" to connect the View layer with the Model layer. For what serializers do specifically, please read the first paragraph of the this page of the official docs.
To answer #1: you almost always do not need to touch either unless you have a very specific use case. In those extraordinary cases:
You override Serializer.create() if you have to customize how model
instances are converted into native Python objects and vice versa. (e.g. create multiple objects)
You override ViewSet.create() if you need to customize how the actual request itself will be processed. (e.g. if there is an additional query parameter in the request, add some response headers)
To answer #2, you almost never need to use is_valid() when using generic views or ViewSets. They already do it under the hood for you. The serializer's .data and .validated_data are a bit tricky to explain. The former contains the Python datatype representation of the queryset/model instances you want to serialize, while the latter is the result of the validation process involved in checking if a Python object conforms to that particular Python datatype representation mentioned earlier, which in turn can be converted into a model instance. If that did not make sense, refer to Serializing objects and Deserializing objects.
As for #3, what do you mean by JSON field? As far as I know, Django does not have a model field called JSONField. Is this from a third party package or your own custom written model field? If so, then you will probably have to find or write a package that will let you integrate it with DRF smoothly and "correctly" whatever that means.
EDIT
Your use case is too complicated. I can only give you rough code for this one.
class MyModelSerializer(serializers.ModelSerializer):
my_json_field = JSONSerializerField()
class Meta:
model = MyModel
def validate(self, data):
# Get JSON blob
json_blob = data['my_json_field']
# Implement your own JSON blob cleanup method
# Return None if invalid
json_blob = clean_json_blob(json_blob)
# Raise HTTP 400 with your custom error message if not valid
if not json_blob:
raise serializers.ValidationError({'error': 'Your error message'})
# Reassign if you made changes and return
data['my_json_field'] = json_blob
return data
def create(self, validated_data):
json_blob = validated_data['my_json_field']
# Implement your object creation here
create_all_other_objects_from_json(json_blob)
# ...
# Then return a MyModel instance
return my_model

How to handle transient data in Django model (or how to avoid a global variable)?

I have a tree of models defined in my Django app (e.g. 'a' is a top level model, which has many 'b's, which has many 'c's). I also have the Views/Templates that render these appropriately. For each one of these models I typically need to do a Database query based on the current logged in user.
For example, it's similar to how each user on stack overflow can mark a question with a star. If my model is the question, I would ask the model if the current user has this question starred and then render it appropriate in the template.
My first thought was to try to pass a parameter in the template (which I now know doesnt' work).
# template
{{ question.is_starred(request.user) }} # Can't work.
My second thought was to have some type of global variable (which I don't like on principle).
# model
class question (Models.model)
def _is_starred(self):
# Use a global variable to find out the current logged in user!
My third thought was to have the View tell the model the currently logged in user, but the trouble is, I have a tree of model objects and I think I'd have to load and set every model in the tree, even if I don't end up using them all. I assume that the objects are lazily loaded.
# view
def view_one_question(request, question_id):
q = Question.objects.get(pk=question_id)
q.SetCurrentlyLoggedInUser (request.user.id)
# !!!! But what about the other network of objects that the question has?
return render_to_response(...)
Any advice is appreciated. I'm new to Django and trying to start this project off with the best design possible.
Your first example is the right idea, but the wrong implementation. You can't pass parameters to methods in Django templates. The easiest way around this is a simple filter:
# yourapp/templatetags/somefile.py
from django import template
register = template.Library()
#register.filter
def is_starred_for_user(question, user):
return question.is_starred(user)
Then, in your template:
{% load somefile %}
{{ question|is_starred_for_user:request.user }}

How to make multiple user types when signing up?

I'm using Django 1.2 and I want to have two user types (one for companies and one for consultants). I will either use an object in my model (something like a boolean for is_company or is_consultant) or Django's groups to distinguish them--depending on which is easier for this problem. I guess it wouldn't be much of a problem if I weren't a total noob ;)
I'm using django-registration for my authentication backend, and I will have a separate form on my webpage for each user type (company vs consultant). I don't think it is best to create two different views that are almost identical for the two cases, so I'm wondering what the best way is to identify/register the users who signed up as either of the two types.
Thanks for your help.
Do you want the user to pick if they are a consultant or company when registering? If so, you can create your own form by subclassing the RegistrationForm and then passing your new form into the parameters for django-registration (Read the doc on how to do that.)
To subclass the form and add the additional field you would do something like so:
from registration.forms import RegistrationForm
USER_TYPES = (
('consultant', 'Consultant'),
('company', 'Company'),
)
class MyRegistrationForm(RegistrationForm):
user_type = forms.ChoiceField(choices=USER_TYPES)
From then, you should catch the signal and do as you need with the form data django-registration has great documentation
Hope that's what you were lookign for.
Rather than looking in the POST, you can pass the information in the query string.
So one "button" (which is really just a link) links to /form?type=consultant, and the other links to /form?type=company and then you can grab it from the GET information

How do you modify the default widget for all builtin form fields of a certain type in Django?

This is a follow-up on How do you change the default widget for all Django date fields in a ModelForm?.
Suppose you have a very large number of models (e.g. A-ZZZ) that is growing with the input of other developers that are beyond your control, and you want to change the way all date fields are entered (i.e. by using jQueryUI). What's the best way to ensure that all date fields are filled out using that new widget?
One suggestion from the cited question was:
def make_custom_datefield(f):
if isinstance(f, models.DateField):
# return form field with your custom widget here...
else:
return f.formfield()
class SomeForm(forms.ModelForm):
formfield_callback = make_custom_datefield
class Meta:
# normal modelform stuff here...
However, is this possible to do where you don't have explicit ModelForm's, but url patterns come from models directly? i.e. your url config is likeso:
url(r'^A/?$', 'list_detail.object_list', SomeModelA)
where SomeModelA is a model (not a form) that's turned into a ModelForm by Django in the background.
At present in my system there are no Forms for each Model. The only point of creating forms explicitly would be to add the formfield_callback suggested in the prior solution, but that goes against DRY principles, and would be error prone and labour intensive.
I've considered (as suggested in the last thread) creating my own field that has a special widget and using that instead of the builtin. It's not so labour intensive, but it could be subject to errors (nothing a good grep couldn't fix, though).
Suggestions and thoughts are appreciated.
It sounds like you want to do this project-wide (ie: you're not trying to do this in some cases, but in ALL cases in your running application).
One possibility is to replace the widget attribute of the DateField class itself. You would need to do this in some central location... something that is guaranteed to be loaded by every running instance of the django app. Middleware can help with this. Otherwise, just put it in the __init__ file of your app.
What you want to do is re-assign the widget property for the forms.DateField class itself. When a new DateField is created, Django checks to see if the code specifies any particular widget in the field property definition. If not, it uses the default for DateField. I'm assuming that if a user in your scenario really defined a particular widget, you'd want to honour that despite the change to your global API.
Try this as an example of forcing the default to some other widget... in this case a HiddenInput:
from django import forms
forms.DateField.widget = forms.HiddenInput
class Foo(forms.Form):
a = forms.DateField()
f = Foo()
print f.fields['a'].widget
# results in <django.forms.widgets.HiddenInput object at 0x16bd910>