What is the best approach to organize classes in models? - django

I have one app, is called "perms" - some custom permission system. Inside the model's file I have this class "Role".
# perms models.py
class Role(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
perms = models.ManyToManyField(Perm)
class Meta:
abstract = True
#def ... some custom functions
Next, I have some apps in my project e.g. app1, app2, app2 etc. were I am using this Role class. E.g.
# app1 models.py
from perms.models import Role
class App1Role(Role):
# some custom fields
The question is if this is good approach or should I organize everything in a different way: to put all "AppXRole" classes in perms.models and then in appX.models import this particular AppXRole class?
What is the best way to manage this kind of app's dependencies in Django?

Related

how to generate builtin model permissions for non-managed models?

I have model like this:
class Venue(models.Model):
name = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'venue'
permissions = [
('change_venue', 'Can change venue'),
]
It is not managed because it already exists in the database (which was created before django project).
I want to use django's builtin model permissions, but they are not created by default. I tried to add them by changing Meta.permissions field but got an error: The permission codenamed 'change_venue' clashes with a builtin permission for model 'events.Venue'
What should I do? Just make migration and create permissions manually?
Fixed by creating permissions in App.ready hook:
from django.apps import AppConfig
from django.contrib.auth.management import create_permissions
class MyAppConfig(AppConfig):
name = 'myapp'
def ready(self):
create_permissions(self)
Don't know if this counts as valid solution tho
Edit 1
Method above didn't work for new database because models "were not ready/create" when app is ready. So I switched to post_migrate signal, and everything was fine.
Edit 2
After some time I have found global problem about why I don't have permissions and content types in the first place: I simply didn't make migrations for un-managed models. With migrations everything is fine.

Is it possible to define views and templates for abstract models to be used for actual models?

Let's say I have a myapp django app and that I need to define 2 specific contact-related models, e.g.
myapp.PersonContact
myapp.CompanyContact
Somewhat obvious thing to do is to create a new contacts app and define an abstract contacts.Contact model which can then be reused in myapp.models, e.g.:
# contacts/models.py
from django.db import models
class Contact(models.Model):
name = models.CharField(max_length=80)
...
class Meta:
abstract = True
# myapp/models.py
from contacts.models import Contact
class PersonContact(Contact):
person = ...
class CompanyContact(Contact):
company = ...
My goal is to abstract as much logic as possible to the contacts app but the only thing that comes to mind is to define an Abstract class contacts.Contact and use that so that I don't have to redefine the same fields in myapp.PersonContact and myapp.CompanyContact.
Is is somehow possible to define contacts.Contact related views and/or templates within the contacts app so that I don't have to create almost identical CRUD-ish views and templates for both PersonContact and CompanyContact?

How to override a Django reusable app's model?

I've installed a django reusable app (Django-Userena) and would like to overwrite the given models.py file.
I have created an app named 'accounts' that calls from Django-Userena. In my 'accounts' app, I have this models.py file that has a class MyProfile that inherits from Django-Userena class UserenaBaseProfile - class MyProfile(UserenaBaseProfile)
In the UserenaBaseProfile class, there is the following code:
privacy = models.CharField(_('privacy'),
max_length=15,
choices=PRIVACY_CHOICES,
default=userena_settings.USERENA_DEFAULT_PRIVACY,
help_text = _('Designates who can view your profile.'))
I would like to extend privacy with an extra value with 'editable=False,' as I do not want this field to be displayed in the auto-generated form.
I tried several ways like calling privacy again in the MyProfile inherited model with the new settings but I am only made aware of Django's "Field name "hiding" is not permitted" (https://docs.djangoproject.com/en/1.4/topics/db/models/#field-name-hiding-is-not-permitted)
My current solution is to simply include the whole UserenaBaseProfile class in my 'accounts' app models.py before calling class MyProfile(UserenaBaseProfile) below.
This does not look like an elegant solution to me. How do you guys go about overriding the models.py file in the reusable app?
Thank you very much.
In my opinion it could be done in two ways:
Make a fork of Django-Userena with your modified model and you use yours.
Make a wrapper of Django-Userena with your models.py and use your wrapper app.
For the urls.py/views.py you could just put:
#Your wrapper views:
from django-userena.views import *
#your wrapper urls:
from django-userena.urls import *
Here are your models:
#your MODIFIED model:
from django-userena.models import *
# then put you new UserenaBaseProfile
class UserenaBaseProfile(models.Model):
#copy the model fields
...
privacy = models.CharField(_('privacy'),
max_length=15,
choices=PRIVACY_CHOICES,
default=userena_settings.USERENA_DEFAULT_PRIVACY,
help_text = _('Designates who can view your profile.'))
Then you could use your custom app in your project.
If you want to customise templates, create a templates directory in your project and put there your modified template files keeping their original names, so the django template-loader could find yours first (it depends how template-loaders have been configured in your settings.py)

Group models from different app/object into one Admin block

Is it possible to group models from different apps into 1 admin block?
For example, my structure is
project/
review/
models.py - class Review(models.Model):
followers/
models.py - class Followers(models.Model):
admin.py
In followers/admin.py, I call
admin.site.register(Followers)
admin.site.register(Review)
This is to group them inside 1 admin block for administrators to find things easily.
I tried that, but Review model isn't showing up inside Followers admin block and I couldn't find documentation about this.
Django Admin groups Models to admin block by their apps which is defined by Model._meta.app_label. Thus registering Review in followers/admin.py still gets it to app review.
So make a proxy model of Review and put it in the 'review' app
class ProxyReview(Review):
class Meta:
proxy = True
# If you're define ProxyReview inside review/models.py,
# its app_label is set to 'review' automatically.
# Or else comment out following line to specify it explicitly
# app_label = 'review'
# set following lines to display ProxyReview as Review
# verbose_name = Review._meta.verbose_name
# verbose_name_plural = Review._meta.verbose_name_plural
# in admin.py
admin.site.register(ProxyReview)
Also, you could put Followers and Review to same app or set same app_label for them.
Customize admin view or use 3rd-part dashboard may achieve the goal also.

How to avoid duplicate models in django project?

i'm learning django so i've many questions, and one is how i can reuse a model? i mean the models live in the application folder, but some models are exactly the same between two differents applications.
So should i rewrite the model every time that i write a new app?
Yes, this is wrong when you have the same names of yours apps
You also can use abstract models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
If your models are exactly the same in different applications, you're doing something wrong. Don't forget that an application is basically just a set of models, and you can use one application's models within another application just by importing them.
Can you give an example of two applications with exactly the same models?
How do I reuse a Model.
Best way to reuse model is to Inherit the parent Model class. This is how you must be doing it. Inheriting from models.Model.
from django.db import models
class trial(models.Model):
# override the parent class methods here or define your own
Also make sure that you import your apps models in the appropriate models.py file.