Unresolved import models Django + Docker - python

I have a few simple classes in my Django app that are not loading/importing properly. I know that the code works as I am Dockerizing over an existing app. I am fairly sure this is a similar issue to this but I do not know how to update this to use the Python inside my Docker container. I am following this guide (so all settings/configuration is the same).
I have 2 classes: a custom user class and a Company model, and I am trying to add a foreign key on the user that links it to a particular Company. On the other side, I will have a many to many relationships (a company can have multiple users).
from core.models import Company
VS Code says "unresolved import" when I hover on core.models

I figured out (kind of) how to fix the problem. This thread was helpful, I added a setting to ignore unresolved imports, I also reordered my imports, also I was opening the folder that contained my app code (the root where the docker-compose.yml file lives) but I needed to open the actual code/source directory.
Setting:
"python.analysis.disabled": [
"unresolved-import"
]

Related

Django include models.py from project to multiple apps

I would like to know if there is a way to include/import the models.py from the project directory to multiple apps without copying the model in each app. Thank you!
Every app must have its own models.py present in the app folder.You have models.py in an app folder you can write the following import statement in any file of your project:
from myapp.models import model_to_import
If you have models.py outside any app folder or any other folder, then make sure that folder contains an (with two underscores)init(with two underscores).py file and just write the following in the file you want to import:
from folder_name import models
from models import model_to_import
You could create an app which contains any models which you need project-wide, e.g.
python manage.py startapp projectcore
and then
from projectcore.models import MyModel
as needed.
But probably better to listen to Ludwik and try to restructure if you can!
You are not meant to put models directly on a project level in Django. Every model have to be associated with a particular app. On the other hand you can import models between apps.
If you feel a need for a project level models it just means you haven't partitioned your functionality into apps properly. There shouldn't be any reason to have "project level models" (or "project level views" for that matter). You just need to split the functionality into separate apps.
Let's say you are designing an intranet website for a school. You would have one app that deals with students' accounts, and another app generating timetables, and yet another one for an internal message board, etc.. Every app defines its own models (there are no "project level models"), but apps can import each others models (so message board posts can have a ForeignKey field pointing at student from the "students" app).

Hyphen in django app

Well I stumbled upon a problem with imports and a Django app that has a hyphen in its name.
As far as I know hyphens aren't even allowed in Django app names but it's still there and the website runs without errors. I have absoltuely no idea of how the app was created since the project already existed when I started working on it. (It's a Django CMS project if that changes anything btw)
Now the problem is that when I want to import something in the shell or in a project I can't just write from my-app import module since it always throws an error because of the hypen.
Also in the INSTALLED_APPS it is listed with the hypen INSTALLED_APPS = ('my-app')
So how can I actually fix this and make it useable? I thought about renaming but I don't really know the consequences and I also don't really want to break anything in the CMS (I'm still learning Django and the CMS is very new to me)
You can do this:
import importlib
module = importlib.import_module('.module', 'my-app')
See documentation for more info https://docs.python.org/3/library/importlib.html#importlib.import_module
Edit: This is not a Django specific issue, it is that in Python (and in most other programming languages) '-' (hyphen) can't be used in variable names (As '-' is the subtraction operator).

Why are there one model.py per app instead of just one model.py out through the whole project?

I was just wondering why each project does not just have one model.py file, considering its just a file full of classes ( acting as database tables), because the whole project runs on one database, why can there be more than one models.py file if all files work with the same database?
Thanks.
So that the apps can be taken and used with a different database if desired without needing to modify the code (much).
Django is set up to have projects that are collections of reusable, self contained apps. Each has its own model.py because they're tied closely to the views and templates for that app but may not be needed for the rest of the project.
Ususally you will start writing one app. Once in a time, you will recognize that there are features which are not very tightly related (e.g. user management or different sub-parts). Additionally, your models.py will start to be lengthy and want to have a clearer structure.
This is the point in time where you start splitting your project in independent sub-parts - the apps. Still, they will work with the same database. And even better: some friendly guys might have built apps whih you can include in your project - each bringing teir models and - of course - interacting with your database.
If everything in yourproject is closely related, there is no need for different apps.

How to bind multiple reusable Django apps together?

I try my best to write reusable Django apps. Now I'm puzzled how to put them all together to get the final project.
Here is an example of what I mean:
I have a picture app that stores, resizes and displays images. Also I have a weblog app that stores, edits and displays texts. Now I want to combine these two to show blog posts with images.
To do that I could put foreign key fields in the blog to point at pictures. But then the blog could not be used without the picture app. Also I could create a third app, which is responsible to connect both.
What is the 'best practice' way of doing it ?
EDIT: Thank you for your very good answers, but I'm still looking for more practical example of how to solve this problem. To complete my example: Sometimes it would be nice to use the blog app without the picture app. But if I hard code the dependency it is no longer possible. So how about 3rd app to combine both ?
Introduction talk in the bottom of the answer (more straight to the answer). I will assume that you have one app for text handling called Text and one app for picture handling called Pictures and a third app for blogging called Blog.
Big picture
You will need to study the manual about the template language for python programmers. The idea is that each thing is in its own app and that you have a third app that connects everything. The apps should then supply its models and views as you like them (just remember to keep you focus on what the app should do) and also supply a set of templatetags.
How to make inclusion tags
Make inclusion tags and it is really easy! It will remind you of writing normal views.
Create a directory templatetags in you app folder. Also create a __init__.py file in this templatetags (so the directory becomes a python package).
Then create a python file. The name is important, you will use this in {% load xyz %} in the templates that will use your app. For instance if call the file picturestags.py, you will call
{% load picturestags %} in all templates that will use it.
First in the file add some politics you need not to think much about, just include this before anything else:
from django.template import Library
register = Library()
Then add the tags by defining functions with the same name as your tag. I will call it display_picture in the example and it will take one argument url. The function should create a dictionary that you will use in a template. My example will just display the picture the url is pointing to.
#register.inclusion_tag('pictures/display_picture.html')
def display_picture(url):
return {'picture': url}
Create the path templates/pictures in your app and create the file display_picture.html inside containing:
<img src="{{ picture }}" />
As you probably understand, the #register makes this a tag, what is inside the dictionary display_picture returns are what you can use in display_picture.html. Very much like your normal view functions.
In the end you will end up with these files:
pictures/
__init__.py
models.py
views.py
tests.py
templates/
pictures/
display_picture.html
templatetags/
picturetags.py
That is all you need to add to your Picture app. To use this in your Blog app, you need to add Pictures to your INSTALLED_APPS. Then in the templates, where you need to use your own newly home baked tag first load it: {% load picturestags %} then just add the tag {% display_picture https://www.google.com/intl/sv_ALL/images/logos/images_logo_lg.gif %} like this:
{% load picturestags %}
<html>
<body>
{% display_picture https://www.google.com/intl/sv_ALL/images/logos/images_logo_lg.gif %}
</body>
</html>
Results
This is just a small example but you can see that it is very easy to expand this. Your blog could connect the Text and Pictures app by importing their models and foreign key them. There is you connection Text and Pictures for a certain blog post. Your blog_post.html-template could look like (simplified):
{% load picturestags %}
{% load texttags %}
<html>
<body>
<h1>{{ subject }}</h1>
<div class="article">{% article_to_html articleid %}</div>
<div class="article_picture">{% display_picture %}</div>
</body>
</html>
Notice that only the Blog has dependencies and it is dependencies it should have (no blog without text and pictures...but pictures can live without text). The look and placement should be and can be controlled by CSS and DIV/SPAN-tags. In this way you can take your Picture app and give it to someone who has no idea about Text app and use it, displaying pictures in different ways probably without ever touching your code!
Inclusion tags is the only thing I know of since I just learned this yesterday. I think it is a convenience provided by Django to make life simple. On the documentation page there are a whole lot more (including how to make "real" tags the hard way without "shortcuts"). So if you find this method to limited, read the documentation...it has lots of examples. It also discusses how to make filters, simple_tags, thread considerations and other advanced stuff.
Introduction
I had this exactly this problem as you and I also wanted something different than the answers I read (I don't say the answers was bad, they helped me learn a lot and gave me insights, but I wanted this I am writing now). I managed to figure something out that is not very obvious, thanks to your question and definitely thanks to Stack Overflow so this is my contribution back even to a half year old question that is probably abandoned (might help a googler or two)!
I also got a lot of inspiration from Google Tech Talk Reusable Apps. In the end (43 minutes) he mentions some good examples like django-tagging which is what he says a model for how to write reusable apps. That gave me the idea for all this, because that is the way django-tagging solves this very problem we had/have.
Now after I written all this (took an hour), I feel for the first time that I might contribute instead of just google and follow what others are doing or complaining that others are not writing how I need to do things. For the first time I am taking my responsibility of writing my view so others can google this (just had to write this paragraph :-) because it feels really great, even if it might be shredded to pieces or ignored and forgotten).
Think of it in the same way that you would use any 3rd-party app in your project. "Re-usable" doesn't mean "without dependencies". On the contrary, you'd be hard-pressed to find an app that doesn't have at least one dependency, even if it's just dependent on Django or core Python libraries. (While core Python libraries are usually thought of as "safe" dependencies, i.e. everyone will have it, things do sometimes change between versions of Python, so you're still locking your app into a specific point in time).
The goal of re-usuable is the same as that of DRY: you don't want to write the same code over and over again. As a result, it makes sense to break out functionality like a picture app, because you can then use it over and over again in other apps and projects, but your picture app will have dependencies and other packages will depend on it, as long as there are no circular dependencies, you're good (a circular dependency would mean that you haven't actually separated the functionality).
This is a good question, and something I find quite difficult to manage also. But - do you imagine these applications being released publicly, or are you only using them yourself? If you're not releasing, I wouldn't worry too much about it.
The other thing is, dependencies are fine to have. The pictures app in your example sounds like a good candidate to be a 'reusable' app. It's simple, does one thing, and can be used by other apps.
A blog app on the other hand usually needs to consume other apps like a picture app or a tagging app. I find this dependency fine to have. You could try to abstract it a little, by simply linking to a media resource that was put there by your picture app.
It's all just a little bit of common sense. Can you make your apps slim? If yes, then try to create them so they can be reused. But don't be afraid to take dependencies when they make sense. Also, try to allow extension points so you can potentially swap out dependencies for other ones. A direct foreign key isn't going to help here, but perhaps something like signals or Restful APIs can.
I am a Django newbie and I faced the same problem. It is shameful how there's so much buzz about reusable apps in the Django community, but not a single authoritative reference on how to connect them
in a project without hard coded dependencies.
I have been working on a new Django project and I wanted to set up my models to avoid hard coding as much as possible. This is the pattern that I used.
Layout
project_root/
core/
models/
mixinmodels1.py
mixinmodels2.py
...
utils.py
...
app1/
models/
__init__.py
base.py
basemixins.py
mixins.py
concrete.py
/signals
__init__.py
handlers.py
utils.py
...
app2/
...
...
App models
base.py : This module implements only the 'reason for existence' of that app in abstract classes.
Rules are:
This module usually only imports from the core app. It usually does not import anything from other apps in the same project.
An exception to the above rule is when the 'reason for existence' assumes the existence of another app. For example, a group app assumes that there is an user app somewhere. In this case, the way to link them is:
# project_root/settings.py
AUTH_USER_MODEL = 'app_label.UserModel'
# project_root/groups/models/base.py
from django.conf import settings
and then using settings.AUTH_USER_MODEL to refer to the user model
Use this pattern for all apps, not just the user app. For example, you should also do
# project_root/settings.py
GROUP_MODEL = 'app_label.GroupModel'
If using the above pattern, only assume the functionality provided by base.py of the other app
to which you are linking. Do not assume the functionality of elaborate concrete classes (I will discuss where to put concrete classes shortly)
Of course, importing from django, third party apps and python packages is allowed.
Make sure that the assumptions that you make in base.py of any app is rock solid and would not
change much in the future. A good example is django-registration by James Bennett. Its an old app, but its appeal did not wane because it made rock solid assumptions. Since good reusable apps do one thing well, it is not difficult to find that set of assumptions.
basemixins.py: This module should implements plugs to the concrete models of that app. A 'plug' to a model M is any model that contains a foreign key to the model M. For example:
# project_root/groups/models/basemixins.py
from django.conf import settings
from django.db import models
class BaseOwnedByGroup(models.Model):
"""
This is a plug to the group model. Use this
to implement ownership like relations with
the group model
"""
owner = models.ForeignKey(settings.GROUP_MODEL,
related_name = '%(app_label)s_%(class)s_owner',
verbose_name = 'owner')
# functionality and manager definitions go here.
class Meta:
abstract = True
app_label = 'groups'
BaseOwnedByGroup is a 'plug' to the group model. The rules here are the same as 'base.py`
While defining 'plugs' in basemixins.py, only assume functionality provided by base.py.
Import only from core, django, third party apps and python packages.
mixins.py : This module should be used for two purposes
To define elaborate 'plugs', which assumes the functionality of the elaborate concrete classes but not the relationships with other apps. The elaborate plugs should ideally inherit one of the 'base plugs' defined in basemixins.py.
To define mixin models (that are not 'plugs') which can be used by the concrete classes of that app.
concrete.py : This module should be used to define (you guessed it) concrete classes of that apps and to set up relationships with other apps. In short, this module assumes your project and all the
functionality you want to provide in it.
Relationships to other apps should be set up as follows:
To establish a one to one or many to one relationship with model M of app another_app, do the following:
# project_root/another_app/utils.py
def plug_to_M_factory(version_label):
"""
This is a factory method which returns
the plug to model M specified by
version_label
"""
if version_label == 'first_version':
from another_app.models.basemixins import BasePlugToM
return BasePlugToM
if version_label == 'second_version':
from another_app.models.mixins import PlugToM
return PlugToM
...
# project_root/groups/models/concrete.py
from groups.models.base import BaseGroup
from another_app.utils import plug_to_M_factory
PlugToMClass = plug_to_M_factory(version_label = 'second_version')
class ConcreteGroup(BaseGroup, PlugToMClass):
# define your concrete model
class Meta:
app_label = 'groups'
To establish a many to many relationship, the recommended way is to use a through model. Inherit the correct plug in the through model in the exact same way (as we did in the ConcreteGroup model)
signals : While setting up relationships, often we have to perform operations on a model M of app app1, when model N of app app2 changes. You can use signals to handle that. Your handlers can assume the functionality of the concrete sender, but often they don't need to. Assumption of the base version of the sender in base.py is enough. This is why it is a good idea to always use settings.ModelName to refer to a concrete model. You can extract out the model class from the settings.ModelName string by either using ContentType or using a project wide get_model_for_settings function as follows:
# project_root/project/utils.py
from django.db.models import get_model
from django.core.exceptions import ImproperlyConfigured
def get_model_from_settings(model_string):
"""
Takes a string of the form 'app_label.model' as input, returns the
appropriate model class if it can find it.
"""
try:
app_label, model_name = model_string.split('.')
except ValueError:
raise ImproperlyConfigured("function argument must be of the "
"form 'app_label.model_name', got '%s'" % model_string)
model = get_model(app_label, model_name)
if model is None:
raise ImproperlyConfigured("function argument refers to model "
"'%s' that has not been installed" % model_string)
return model
core : The core app is a special app which stores project wide mixin functions.
These mixins should not assume anything about any other app. Only exception to this rule is mixins that rely on base functionality of settings.AUTH_USER_MODEL. This is because you can safely assume that most projects will have an user model.
Of course imports from django, third party and python packages are still allowed
Remember that all base.py and basemixins.py modules are allowed to import from core.
Finally for everything to work as intended, import your models in models/__init__.py of every app.
The advantages that I find from following this scheme is:
The models are reusable. Anyone can use the abstract base models and mixins to design their own concrete model. base.py, basemixins.py and related factory methods can be bundled together with a bare bones concrete model and shipped in a reusable app.
The apps are extendable. All mixins are versioned and there is a clear inheritance scheme.
The apps are loosely coupled. External mixins are accessed via factory methods and external models are referred to using django.conf.settings.
The apps are self contained. Any changes in an app will most likely break that app and that app only. Other apps will most likely remain unscathed. Even if external apps break, the place where this
could happen is clearly marked.
I have been using this scheme to reduce coupling between my apps. I am not an experienced Django programmer, and I have a lot to learn, so any feedback is appreciated.

Django - non app specific models.py?

I have multiple Django apps, and I have some code in one of my models.py that really applies to all of the apps. Is there a way to move it somewhere generic, outside of a specific app folder?
Examples of non app specific code I have:
def update_groups(sender, user=None, ldap_user=None, **kwargs):
...
django_auth_ldap.backend.populate_user.connect(update_groups)
A function to correctly identify users, and connect to the correct signal.
I also have a model proxy of django.contrib.admin.models.LogEntry and a modelAdmin of that model proxy so users in the admin site can view the change history. But these really don't belong in any one app's models.py.
Well, just create a python module somewhere in your project and then refference it in your models. To do this, you need a directory with __init__.py file:
helpers/
__init__.py
functions.py
Put your code into the functions.py and in any other place you will be able to:
from helpers.functions import update_groups
post_save.connect(update_groups)
Name of the module is up to you, ofcourse.
You could create a template app that could be used or extended (class hierarchy) by all your other apps that could use that code.
__init__.py in my project's directory seems to be a good place to put this stuff. It gets run right away when the server starts so it's available to everything else. It seems to work fine so far.

Categories

Resources