What are swappable models in django? - python

Hello I am new to django. I have came across the term Swappable model, while reading about django models. I am not able to find the significance of Swappable model.
I have also inspected Model._meta object. It contains a member attribute swappable, which is None by default.
I have tried to search documentation. I have also googled out, but couldn't find any reference to swappable model.
Thanks in advance.

The term Swappable refers to the UserModel of django [1], which can be swapped inside of a project into a custom implementation and as long as you provide the proper API it works with other apps that rely on this API.
The documentation regarding migrations needs to take care of this topic, as it is related to ORM.
Swappable is considered to be private API, but there is also wq/django-swappable-models which makes this concept reusable for you in your app.

Related

Extend User Model or Custom Pipeline in Social-App-Django

I am implementing social-app-django (not the deprecated one; the one that relies on Python-social-auth) with django 1.11 (not using Mongo). My application will need to store and manipulate a lot of data on users other than that which is fetched from their social media accounts at login.
I don't need to fetch or collect any extra data when the user authenticates, but various actions they perform on my site will need to be saved to their user model. I am wondering which of the following approaches is preferred (I've searched extensively online, but can't find a specific explanation of why to use one vs the other):
Create my own user model in my app's models.py (call it MyUser) that doesn't extend anything special, and then add a function in the authentication pipeline that associates the social-app-django user with a corresponding instance of MyUser. Leave AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL unchanged.
or...
Create my own user model in my app's models.py, and in the project's settings.py set AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL to point to MyUser. Leave the pipeline unchanged. In this case, I was wondering whether someone could clarify what MyUser and its manager should extend, and what I need to import in modules.py (I am confused because a lot of stack overflow posts are referring to deprecated versions of this module and I keep getting errors). Also, in this case should I be setting both AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL, or just one of them?
Do these two methods essentially achieve the same thing? Is one more reliable/preferred for some reason? Or, should I be doing both? Thanks very much for any assistance.
Another detail: I would like to be able to access the User database not only from the app I am currently building, but also from other apps (within the same Django project) that I will build in the future. Does this affect anything?
Since I see this has a decent number of views I will post the solution I eventually came to.
Both django and social-app-django (or any other social auth module) make use of the default User model for authentication. While it's possible to edit this model to add custom parameters, I don't recommend it. It's not good abstraction or modularization. If you make a mistake when configuring the model, you won't just break a specific feature on your site, but you might also break the authentication itself.
The only circumstances I can think of under which you'd want to edit the default user model itself is if you need to make changes that affect the authentication flow itself (for example, adding your own custom authentication provider).
It's much easier and safer to create a new model called UserProfile, with a required one-to-one relationship to a User object. Now, you can treat the User object as the authentication part, and the UserProfile object as the content/storage part. You won't have to mess with the User model very often, and the UserProfile model doesn't matter for authentication purposes. Note that in this configuration you should NOT need to change the AUTH_USER_MODEL or SOCIAL_AUTH_USER_MODEL fields in the settings.py file.
If you take this approach, you will need to add a custom step in the authentication pipeline in which you create a new UserProfile object and associate it with the User who is currently logging in.

Django: extending user model vs creating user profile model

I'm creating an app in Django and so far I have been using an extended user model like so:
class MyUser(AbstractBaseUser):
...
with all the user and profile info, but I see a lot of people creating different models for the profile and the user itself on stack overflow, using OneToOneField, although those are mostly old questions.
My question is: which is better and, if there isn't a best among them, what are the advantages for each solution?
thanks!
It depends on what you want to do -- if you're happy with the User model as it stands in the latest version of Django you should just use that -- it's easy and you'll get a lot functionality that goes along with it -- for example a pretty good permission system, and you can be sure to be compatible with all third party modules. But if you thing you'll need to expand on the User model, it's pretty straightforward how to do it. You might find that in the future you need to add more methods to your model than you expected.
The examples that you see with separate UserProfile / User model are mostly a legacy of django < 1.5, where that was the recommended way to extend the User model. There's no reason to follow that pattern any more -- it's a lot more work to have to use two models where you just want one model
**2019 Update**
If you are starting a new Django project, you should always create your own custom user model that inherits from AbstractUser, as per the Django documentation, i.e.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
even if you don't need any additional functionality. The reason for this is that for very low effort, you are making it easy to customize your user object in the future. It's very laborious to replace the built-in User object with your own after you have run the initial migrations, unless you're able to delete all of your data and migrations and start over.
I find some useful information in Django docs:
Extending Django’s default User¶
If you’re entirely happy with Django’s User model and you just want to
add some additional profile information, you could simply subclass
django.contrib.auth.models.AbstractUser and add your custom profile
fields, although we’d recommend a separate model as described in the
“Model design considerations” note of Specifying a custom User model.
AbstractUser provides the full implementation of the default User as
an abstract model.
And:
Model design considerations
Think carefully before handling information not directly related to
authentication in your custom User Model.
It may be better to store app-specific user information in a model
that has a relation with the User model. That allows each app to
specify its own user data requirements without risking conflicts with
other apps. On the other hand, queries to retrieve this related
information will involve a database join, which may have an effect on
performance.
So if I reads it correctly, it means if the fields are related to authentication, then you should consider substitute the original User model. But if it's not related, like profile fields, such birthday, or profile_image, then you might want to create a standalone app that reference the original User model.
And a good tutorial I found: http://riceball.com/d/content/django-18-tutoria-52-adding-user-profile
A ForeignKey is to create a one-to-many relationship. In other words, it will return a queryset. For example, a single car has many wheels, but one wheel isn't attached to several different cars.
A OneToOneField will create a relationship between strictly two objects. For example, the rim belongs to the front-left tire, and only that tire has that rim.
Does that make sense?

Is it safe to access ._meta directly in your django app?

Django uses Meta class for lots of additional object information. However, they store this information in an object '_meta' which by naming convention is private.
All over the django admin (and other places) I see stuff like opts = model._meta and then they use the various options like app_label and verbose_name.
Can I be confident accessing ._meta and be sure that it will not change in the future, or am I better off creating one 'accessor' mixin or something that accesses the ._meta in one spot, so if it ever does change I only have to update one thing?
I use _meta frequently and haven't had any issues so far. You can see in the django documentation an example of them using it too here, so I have felt its more or less ok to do. Just tread carefully and write good tests so you know of any problems when you upgrade your django version later on down the road.
I use _meta in several projects where I want to have generic access to information that's otherwise not provided by the api. I think you're probably okay most of the time as Django is pretty stable. It's probably a good idea to be covering your usage of _meta in your unit tests.

Country-based Super User Access, and modifiying Django Auth

I'm looking to give super user access to users of a program I'm devving.
All the entities have a country id value, so i'm just lookign to hook up my user model to have a country ID
Looking at Django Auth, It should be nice and easy to add a super_user_country_id field.
However, how frowned upon is it to modify the core django classes?
Is there any easier way to go about this or?
At the moment, the recommended way is to create a Profile model and link it to the User model with a OneToOneField or a ForeignKey (depending on your requirements). Here's a good tutorial on the topic.
The Django devs have repeatedly expressed their intent to make extending the User model more straightforward, but AFAIK, no concrete design has been proposed, yet.
Adding a custom UserProfile would be one way to go about this. UserProfile can link to Country and you can prevent users based on their UserProfile. I found James Bennett's article on extending the User model useful when I had a similar requirement.
It is generally not a good idea to patch auth (or other built in) classes. Custom patches can become a pain to maintain and keep up to date.

How to preload model for ReferenceProperty?

I have a models in different files (blog/models.py, forum/models.py, article/models.py). In each of this files I have defined model classes with application prefix (BlobPost, BlogTag, ForumPost, ForumThread, Article, ArticleCategory).
Also I have appliation - comment, for adding comment attached to any model object. For example, I want to comment BlogPost, or add comment referenced to ForumPost. For this I use property with type ReferenceProperty() - without specify type of references. Any model can attached to comment.
What a problem? If I have show all comments in administration section, I see a problem with autoloading models for ReferenceProperty. I don't know, what type of model used for current comment. I need to autoload package with model, if this need.
Yes, exists simple solution - include all models from all applications. But, this is not good solution. I need load only need models. How to do this autoloading?
My idea is based on detect kind of property, and by first part of this name detect application name for load all models in this application. For example, I have comment with Reference to BlogPost model. I get name of application - Blog and load all models from blog.models import *
For implement my idea I need to understand - how to intercept creating property instances. In my case, if I loop over comments, I see that App Engine automatically (thanks, but not in my case) create instances for properties.
How to inject my logic for loading my models before creating property instance?
Thank you!
This isn't possible in the standard db framework, as there's not enough information present to find your models. The only information the framework has to work with is the kind name, which doesn't include the fully qualified package - so it has no way to figure out what package your model definition might be in.
If you're writing an admin interface, though, you probably want to use the low-level google.appengine.api.datastore interface, instead, which operates on dicts instead of model classes, and doesn't require a model definition.

Categories

Resources