Managing Django Apps for Inter-related models - django

For Django, the best practice is apparently to have 1 app to do only 1 thing and to do 1 thing right...and so they can be "plugged and played" to other projects
Consider I have a library application and there are 3 apps. book, member and loan. Each of them has their own model.
So in, say forms.py in loan, I will need to do something like this:
from book.models import Book
from member.models import Model
from .models import Loan
#Other key imports
class CreateLoanForm(forms.Form):
# Some fields
def save(self):
# Retrieve fields
selected_book = self.cleaned_data.get('selected_book')
selected_member = self.cleaned_data.get('selected_member')
new_loan = Loan(
book=Book.objects.get(id=selected_book),
member=Member.objects.get(id=selected_member),
date_start=self.cleaned_data.get('date_start'),
date_end=self.cleaned_data.get('date_end')
)
My questions are:
Doesn't the above from book.models ... violate the ability to plug and play apps?
Is there a better way to import these models? Am I violating best practices when doing so?

For "one app to do one thing, and one thing right" does not mean that it has to have only one model. If you are writing a Library Application then it should have the book, member, and loan models in the same app.
In the context of you question, however, one possible practice to use models from application A in application B would be to define the model as a pluggable setting in app B. See for example what the auth module is doing here: https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#substituting-a-custom-user-model

Related

How do I import from current app in Django without using the app name?

My app is full of statements like this:
from my_app.model import Customer
While it works, I'll like to have a way to reference the current app without hard coding the app name into the import. Something like:
from keyword_for_current_app.model import Customer
Is there a clean way of achieving this with Django?
This is more of a python question than a Django one as it relates to how imports work. As far as I know, there isn't a way to do it as you describe, unless you change the structure of your files.
However, it isn't impossible to do something using Django's functionality to dynamically import models. You could swap some of this with importlib if you need a more general import rather than just returning the model class:
from django.apps import apps
# option 1
model = apps.get_model('app.Model')
# option 2
def get_model(model_name):
return apps.get_model(f'myapp.{model_name}')
# option 3
def get_model(model_name):
for model in apps.get_models():
if model.__name__ == model_name:
return model
The problem with option 1 for your use case is that you still need to specify the app name. Option 2 is an improvement, but you are hardcoding the app name into the function. Option 3 is the best, but might be problematic if you have models with the same name but in different apps/tables.
In my opinion, you should import each model explicitly at the top of your files. This is the cleanest and most readable way - if someone were to read your code, they would expect models to be imported this way.

I was trying to use apps.get_model function. And, I want to use this without specifying the app name, is there any way to do that.

I was referring this link : Django: Get model from string?
. And, I found there is a way to do this by using apps.get_model. But,In my scenario, the model can be from other apps. So, I can't actually name the app_name here. Is there any way to do this ?
If you don't care which app the model comes from, you can do it the following way:
from django.apps import apps
def get_model_from_any_app(model_name):
for app_config in apps.get_app_configs():
try:
model = app_config.get_model(model_name)
return model
except LookupError:
pass
model = get_model_from_any_app('SomeModelName')
But in Django models in different apps can have the same name, i.e. your project can have model Post in your blog app and model Post in your news app etc.
So this way you can end up with not the model you expect, if they have duplicate names across apps (i.e. you probably should not do it this way, just think why in the world would you want a semi-random model?).
Docs which explain the code:
https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.apps.get_app_configs
https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig.get_model

How to handle users and roles by app in Django

Hello everyone let me ask something about the admin interface and how can I handle my users by app.
Well so sorry I'm nooby first of all. So, I need to create a new app for basically take some quiz so I will need users and these users within my app should have a different role as a student or teacher and so on.
The thing is that I don't know if the admin Django interface is just for the DB models or whether I can use it as a security layer in my app.
Or otherwise, I should create a buck of tables in my app model for users and roles and then handle everything from the model because the admin is just the DB access. what could you tell me? thanks so much.
From Django's documentation about Django admin - Link
model-centric interface where trusted users can manage content on your site.
Django comes with a user model, you can extend it to represent teachers and students as described in django's documentation here, you would create ModelAdmins and register your models. Beyond that you can manage your users easily through the admin system, example code:
models.py
from django.contrib.auth.models import User
from django.db import models
class Teacher(models.Model):
user = models.ForeignKey(User, related_name='teacher')
class Student(models.Model):
user = models.ForeignKey(User, related_name='student')
admin.py
from django.contrib import admin
from .models import Teacher, Student
admin.site.register(Teacher)
admin.site.register(Student)
As for security, it is not clear what you mean by "use it as a security layer in my app", if you elaborate more, people can better help you. You can generally learn about security in django here.

whats the difference between Django models and forms?

I am new to Django and can't understand the models and forms. Can any one suggest me the differences and tutorials related to them.
Basically, a model encapsulates information about something (i.e., it models it), and is stored in the database. For example, we could model a person:
from django import models
class Person(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
height = models.FloatField()
weight = models.FloatField()
Whenever a model instance is created and saved, Django stores it in the database for you to retrieve and use at a later date.
On the other hand, forms correspond to HTML forms, i.e., a set of fields which are presented to the end user to fill some data in. A form can be completely independent of a model, for example a search form:
from django import forms
class SearchForm(forms.Form):
search_terms = forms.CharField(max_length=100)
max_results = forms.IntegerField()
When submitted, Django takes care of validating the values the user entered and converting them to Python types (such as integers). All you then have to do is write the code which does something with these values.
Of course, if you have created a model, you will often want to allow a user to create these models through a form. Instead of having to duplicate all the field names and create the form yourself, Django provides a shortcut for this, the ModelForm:
from django.forms import ModelForm
class PersonForm(forms.ModelForm)
class Meta:
model = Person
As for further reading, I would start with the Django documentation, which includes a tutorial on creating and using models, and a fairly in-depth look at forms. There are also plenty of Django books and online tutorials to help you along.
Models are related to the database abstraction layer covered in Tutorial 1:
http://docs.djangoproject.com/en/dev/intro/tutorial01/
It covers everything from what they are, what the philosophy is, what it's abstracting (raw sql). Read it and come back if you have any questions, because it's really good.
Tutorial 4 covers forms.
http://docs.djangoproject.com/en/dev/intro/tutorial04/
The forms framework is just a helper for HTML forms. There are also ModelForms, based on the forms framework, that ties models together with forms, but the core of it is a framework for dealing with HTML form display, validation, and processing.

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.