Questions about extending any Django app - django

My old worker installed Pinax through PIP and it's installed in site-packages. All the apps lives there. Our own apps are within our Django project structure.
I want to modify Pinax's account app, by switching the create_user's is_active flag to False. Currently, the app makes it True. I also want to add additional functionality to create_user or whatever function I want to do.
from pinax.account import forms
class MyCustomizeForm(forms.SignupForm):
def create_user(....):
super(....)
// additional...
Maybe this?
But doesn't that require me to do at least two commit transactions talking to DB?
Is that preferable? Also, does doing this require me to change anything else in my Django project (how users signup, what views it uses... what forms it uses)?
Currently, I've an app living in my Django project supposes to deal with the extension / customization of account app. I can't commit site-packages to VCS.... I mean.. I am not supposed to make any changes there.
Thanks.
Pinax account/models.py
class Account(models.Model):
...
def its_own_method(...)
# this is in the same indentation level as class Account
def create_account(sender, instance=None, **kwargs):
if instance is None:
return
account, created = Account.objects.get_or_create(user=instance)
post_save.connect(create_account, sender=User)

You can use the django signals for exactly this situation. Signals are meant for apps that need to be distributed generally and won't always know how they will be integrated into a project.
The signal of interest to you here is the pre_save. You can connect a pre_save to the pinax.account model and be notified when a save is about to happen. This will give you a chance to make changes to that model instance. Signals are synchronous, meaning you are making your change serially, right before the pinax.accounts will finish committing the save

Related

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.'))

Notification to user from admin

I am new in Django and don`t know the best way to realise next functionality in my project.
In my django project I have users with different roles. One of them is admin who can create project. I mean that I have model with fields (project_name, project_managers) which filled by admin. The managers of the project are users of the system, admin can choice some of them. After all how to show them notification in real time that they was managers of the current project. Is it makes by websockets or Jquery or something else. I need some ideas how to realise that with detail explanation if it possible.
You can use post_save signal to implement your notification functionality. This signal will be called once the model object is saved.

One Django Project, Multiple Settings.py

Recently I am to develop a CRM system with an e-commerce module. Since customers only log into the e-commerce website (log in with Email), staff only log into CRM,
I want to separate these two authentication model. Is it a good idea to have two sets of settings.py, one using staff as AUTH_USER_MODEL, the other one using customer as AUTH_USER_MODEL? (Maybe separate urls.py as well)
I'm going to run two different settings of app under two sub path or two domain, is this going to cause any issue? (Like concurrency issue ?)
you dont need to set two AUTH_USER_MODEL = 'myapp.MyUser' 's or two settings for this purpose which probabyly would work but this is not the level this logic belongs to. (settings is already in deployment level e.g. running multiple websites on the same codebase and same databse etc etc...)
what I would recommend is something simple:
# settings.py
AUTH_USER_MODEL = 'yourapp.CustomUser'
# yourapp's models.lpy
from django.contrib.auth.models import User
class CustomUser(models.Model):
user = models.OneToOneField(User, related_name="customuser")
crm_staff = models.Boolean(default=False)
# ...
and depending on crm_staff, the user is either crm-user or just an external user. I set the default value of crm_staff to False, so that you have to give it explicitly everytime a new user comes in, but only if user is a crm staff, then you need to set the field to True
keep it as simple as possible, you say thanks to yourself for this later..

Project platform suggestion for web application with proper User Auth and integration support

So, I have an idea to build a web app. I am new to this business but am a programmer. I liked Python and thought let me start with Django. I ran into a problem with the built-in Django User Auth system as pointed by this question of mine on SO.
In short, I am using Django's built-in User auth and thought that it will easily fill my user field (the foreignkey) in my model but it does not. I have Googled and asked questions but only got a very convoluted answer or that I have to use the Admin section if I want anything like that.
My simple need is that whenever user saves anything in their profile, the user field should get populated so that I can reference it. To me, it sounds like the most basic need for any web app.
Am I wrong. I need advice. If Django is not good for this then I am ready to learn any other good framework or platform if need be.
In short, I am using Django's built-in
User auth and thought that it will
easily fill my user field (the
foreignkey) in my model but it does
not.
This won't just magically happen. You will have make it happen. Models are separated from the request so this would happen in your view, or a model method (perhaps save) that is passed the active user.
MVC / MTV design separates the database from the view / control logic. I don't see what framework has to do with this: unless you write the functionality yourself, the database doesn't know what to do with some User table and the currently logged in user (also separated from the data). Building in this functionality would inconvenience a lot of people as well...
In general, the python/django philosophy is: Explicit is better than implicit.
Now the solutions:
If you wanted this behavior in the view, for any form, you could potentially write:
instance = MyForm.save(commit=False) # commit=False prevents DB save.
instance.user = request.user
instance.save()
You could overwrite the save method on the model that accepts an optional user argument as well.
def save(self, *args, **kwargs):
user = kwargs.pop(user, None)
self.user = user
super(MyModel, self).save(*args, **kwargs)
mymodel = MyModel()
mymodel.save(user=request.user)

Sharing models between Django apps

I will be brief: to work in the spirit and idea of a Django app, it is ok for an app to import models from inside another app ? Say, a User statistics app will import models from a User app something like: from users.models import users
The answer is yes. It's perfectly okay for one application inside your django project to import models from another application. The power of a django project lies in the apps and their interactions.
Also make sure that you have utility applications importing models from more generic applications and not the other way. So "userstatistics" app should import models from the "users" app but "users" app should not rely on the "userstatistics".
If your app is importing models from a 3rd party application (lets say django-piston), be sure to specify that in a requirements file.
If you're building an internal app that has no chance of ever being released to the public, sure, do whatever you want.
If you're building an internal app that has little chance of ever being released to the public, but will possibly be used by future/current developers, sure, but be sure to document what the app needs to work properly.
If you're building an app for public release, try to keep it self-dependent (and django-internals dependent, ie, use what django provides, when possible). If you really need a third-party app to work, or if a third party app would make your code more manageable, then sure, include dependencies, but be doubly sure to document all requirements and necessary setup.
In most cases, you can do almost whatever you want so long as you have sufficient documentation.
I do, however, have to question the sanity of making your own User model that has the same name as django's builtin auth.User.
You cand try better extending the Django User model with inheritance. You will use the django user with custom field added, so you will have the same user for all the apps.
You can directly import models in app2/models.py. Usually you might need a foreign key, which looks like
models.ForeignKey('app1.ModelClass1', on_delete=models.CASCADE, related_name='modelclass2')
Don't do this. They will have the same app name and the ORM will be confused. Use an abstract model instead, and have both derive from it.