Django testing: TemplateDoesNotExist when loading fixtures. Why? - django

I have an automatic welcome message generated from template, which is sent whenever a new user is created (through a post_save signal for the User model). Everything works as it should, except when I run manage.py test.
Django keeps complaining:
Problem installing fixture '.../lib/python2.7/site-packages/django/contrib/auth/fixtures/context-processors-users.xml
...
TemplateDoesNotExist users/email_welcome.html
when trying to load the django.contrib.auth fixtures for testing.
Why is it so? Are the template loaders not present when loading fixtures? What could be a solution to this?

I don't know why there is a problem with this template (it works for me), but probably during fixtures loading you don't want to generate this email. In this situation you can use raw argument wich is sent with signal. From Django docs about raw:
A boolean; True if the model is saved exactly as presented (i.e. when
loading a fixture). One should not query/modify other records in the
database as the database might not be in a consistent state yet.
So your code should look like this:
#receiver(post_save, sender=User)
def generate_email(sender, instance, created, raw, **kwargs):
if not raw:
# generate email from template

Related

What is views.py for?

I am currently learning how to build a backend and I have only used the views.py file to set up Django Rest Framework. Almost everything is happening in my models.py or admin.py file.
Is that a problem? What even is views.py for?
I should add that I will be using Angular for the frontend later!
The convention is you that you write the logic that connects to your db in views.py but then you can define the view anywhere you prefer even inside the models.py so long as you're able to call it when needed.
For more, check.
this here
Django works on MVC model which enables to structure data and template individually.
In django we retrieves the data from the models in views and render that data with a template. So view processes the data with our logic and give that data to template.

Does Django create useless migrations?

When I change the verbose_name attribute of a Django Model, Django will generate a related migration (running make migrations command).
However, without applying the migration (migrate command), the change seems to be applied all over the Django project. I think this is because verbose_name is something used at Django level rather than at database level.
This makes me wonder: what is the purpose of this migration file?
Django makes abstraction of the backend used. Indeed, you can use a different backend, by altering the settings.py file. In fact you can define a backend yourself.
All changes to the models thus can have impact on the database. You could for example define a backend that uses the verbose_name of a column as the "comment string" you frequently can add to such column at the database side. If you for example define choices, then a backend could, for some databases, try to enforce these choices at database level.
Since, as said before, Django aims to work unaware of the backend used, it thus aims to be conservative, and make migrations for a lot of model changes. For some of these, the backend will decide to simply do nothing. So no query is constructed, and nothing is changed at the database side. You can indeed see such changes as "useless migrations". But keep in mind that if you later would use a different backend, these "useless migrations" might in fact do something.
Since such migrations do not do anything on the database side, these are however usually not time cosuming. You might want to look to "squash" migration files [Django-doc] together, and thus reduce the number of migration files used. The migrations will still be part of the file, but since there are no queries involved, it will usually not do much harm.
Furthermore, you can in fact patch the deconstruct function on a field, such that the help_text, etc. do not appear in the result of a deconstruct call anymore and thus are not visible to the "detector". This Gist script shows a way to patch the makemigration command:
"""
Patch the creation of database migrations in Django
Import this early from `__init__.py``.
- Don't want verbose_name changes in the migrations file.
- Don't want help_text in the migrations file.
"""
from functools import wraps
from django.db.models import Field
def patch_deconstruct(old_func, condition):
"""
Patch the ``Field.deconstruct`` to remove useless information.
This only happens on internal apps, not third party apps.
"""
#wraps(old_func)
def new_deconstruct(self):
name, path, args, kwargs = old_func(self)
# AutoField has no model on creation, but can be skipped
if hasattr(self, 'model') and condition(self):
kwargs.pop('verbose_name', None)
kwargs.pop('help_text', None)
return name, path, args, kwargs
return new_deconstruct
Field.deconstruct = patch_deconstruct(Field.deconstruct, lambda self: self.model.__module__.startswith('apps.'))

How to execute code after authentication in Django?

I want to execute one or more functions after a user logs into my site. How is this possible? I looked into Middleware. Djangobook says that I'll need this to run a piece of code on each and every request that Django handles. However, I just need the code run when the authentication happens successfully.
Note: I am using Django Allauth for authentication and I don't have any view of my own to log in users.
You need to tap into Allauth's signals. Specifically the user logged in signal
allauth.account.signals.user_logged_in(request, user)
Sent when a user logs in.
So add code similar to the following in your project.
from django.dispatch.dispatcher import receiver
from allauth.account.signals import user_logged_in
#receiver(user_logged_in, dispatch_uid="unique")
def user_logged_in_(request, user, **kwargs):
print request.user
This code should be in a place that's likely to be read when django starts up. models.py and views.py are good candidates.
As per the official documentation, there is a signal allauth.account.signals.user_logged_in which gets triggered when a user logs in. This can serve your purpose.

More Blobstore upload woes with standard Django

I'm implementing an image upload feature for my Django app (plain Django 1.4 , NOT the non-rel version) running on Google App Engine. The uploaded image is wrapped in a Django model which allows the user to add attributes like a caption and search tags.
The upload is performed by creating a Blobstore upload url through the function call blobstore.create_upload_url(url). The function argument is the url to which the Bobstore redirects when the upload is complete. I want this to be the url of the default Django form handler that performs the save/update of the model that wraps the image so I don't have to duplicate default Django behaviour for form validation, error reporting and database update.
I tried supplying reverse('admin:module_images_add') to create_upload_url() but this doesn't work as it throws an [Errno 30] Read-only file system exception. I presume this originates from the default Django form handler again trying to upload the file the standard Django way but then hits the brick wall of Google App Engine not allowing access to the file system.
At the moment, the only way I can see to get this working without duplicating code is by strictly separating processes: one for defining an image model instance and the second for uploading the actual image. Not very intuitive.
See also this question and answer which I posted earlier.
Any suggestions on how to get this working using one form and reusing Django default form handlers?
EDIT:
I've been reading up on decorators (I'm relatively new to Python) and from what I read, decorators appear to able to modify the behaviour of existing Python code. Would it be possible to change the runtime behaviour of the existing form handler to solve the above using a decorator? I obviously have to (1) develop the decorator and (2) attach it to the default handler. I'm not sure if (2) is possible as it has to be done runtime. I cannot patch the Django code running on GAE...
Well, I finally managed to get this working. Here's what I did in case anyone runs into this as well:
(1) I removed the ImageFile attribute from my model. It ended up causing Django to try and do a file upload from the file system which is not allowed in GAE.
(2) I added a Blobstore key to my model which is basically the key to the GAE BlobStore blob and is required to be able to serve the image at a later stage. On a side note: this attribute has limited length using the GAE SDK but is considerably longer in GAE production. I ended up defining a TextField for it.
(3) Use storage.py with Daniel Roseman's adaption from this question and add the BlobstoreFileUploadHandler to the file handlers in your SETTINGS.PY. It will ensure that the Blobstore key is there in the request for you to save with your model.
(4) I created a custom admin form which contains an ImageField named "image". This is required as it allows you to pick a file. The ImageField is actually "virtual" as its only purpose on the form is to allow me to pick a file for uploading. This is crucial as per (1).
(5) I overwrote render_change_form() method of my ModelAdmin class which will prepare a Blobstore upload url. The upload url has two versions: one for adding new images and one saving changes to existing. Upload urls are passed to the template via the context object.
(6) I modified the change_form.html to include the Blobstore upload url from (5) as the form's action.
(7) I overwrote the save_model() method of my ModelAdmin:
def save_model(self, request, obj, form, change):
if request.FILES.has_key("blobkey"):
blob_key = request.FILES["blobkey"].blobstore_info._BlobInfo__key
obj.blobstore_key = blob_key
super(PhotoFeatureAdmin, self).save_model(request, obj, form, change)
This allows me to retrieve the blob key as set by the upload handler and set it as a property of my model.
For deletion of image models, I added a special function which is triggered by the delete signal of the model. This will keep the Blobstore in sync with the image models in the app.
That's it. The above allows to upload images to the blob store of GAE where each blob is neatly wrapped in a Django model object which admin users can maintain. The good thing is that there's no need to duplicate standard Django behaviour and the model object of the image can easily be extended with attributes in the future.
Final word: in my opinion the support for blobs in plain Django on GAE is currently very poor considering the above. It should be much easier to achieve this, without having to rely on Django non-rel code and a rather long list of modifications; alternatively Google should state something about this in their developer documents. Unless I missed something, this is undocumented territory.

Updating when database has changed in Django

I have many records in my database that are displayed on a screen. However, the records are user generated and sometimes have to be removed. Each record has a show field which is initially always set to true. When we get content that has to be removed a human will set it to false in the Django admin interface. When this happens, we need the bad content to be removed from the screen. So my question is, in the Django interface, what is the way to tell when a record has been updated and do something in response to this change?
You should read about signals:
An Idea on how doing this:
from django.core.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=MyModel)
def my_handler(sender, instance, created, raw, **kwargs):
if created: # True for save, False for update
...
I think this could help you tell when the record its being updated and when you can do something about it.
But if the user seeing the records wont have to refresh the page so the record is hidden, then you could use websockets to receive that information your signal sent. Or you can just do ajax requests every 20-30 seconds to check all the records and discovery which one is hidden, or you can check a list of latest hidden records that your signal will populate.
Anyway, there is different ways of doing this.