Attempted relative import beyond toplevel package in django - python

the code is not been working due to the error in assigning the path properly please help me with that.

Try this in your models:
#Remove the import statement: from blog.models import sighinmodel
#Then, inside your model
user = models.ForeignKey('blog.sighinmodel' , on_delete = None)
Also, I would like to point out that this is not the correct way of importing other modules in your models.py .
You should do like this:
from appname.models import ModelName
#for importing from another module's models.
There is no need for relative path names in import statements in Django. from appname.module import function/class works fine for nearly all the cases until cyclic redundancy occurs, in which you have to take one among many methods. One is the way I mentioned above:
Method 1: Simply put this inside the ModelClass. Don't import anything.
user = models.ForeignKey('blog.sighinmodel' , on_delete = None)
Method 2(when cyclic import condition is not arising)
from blog.models import sighinmodel
class SomeModel(models.Model):
user = models.ForeignKey(sighinmodel , on_delete = None)
NOTE: The above will work only if a cyclic import isn't occurring. In case the cyclic import condition is occurring, switch back to the first method of declaration.
Hope this helps. Thanks.

This error is coming because relative imports are not allowed beyond top level package. Your blog is itself a module so if you import your model from there it would work.
from blog.models import User, sighinmodel
I would also suggest you to use CamelCase for your models name since they are classes for naming conventions.

Related

Django simple app causes a circular import error, followed by a definition error

I'm having a seemingly simple definition error whereby the class Automation is not defined. I've created a very simple app called automations which seems to have caused a problem despite barely changing it. Note that there's also another app called messages, with a many:many relationship with the new automations.
Automations is just an app with this simple models.py file:
from django.db import models
from accounts.models import Account
from messages.models import Message
class Automation(models.Model):
name = models.CharField(max_length=100)
description = models.CharField(max_length=200)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
messages = models.ManyToManyField(Message)
def __str__(self):
return self.name
And messages is a separate app with this models.py file:
from django.db import models
from accounts.models import Account
# from automations.models import Automation # < FAILS
from automations.models import * # < WORKS
# from apps.get_model(email_messages, Message) # < FAILS
# from django.apps get_model(email_messages, Message) # < FAILS
# from django.apps import apps # < FAILS
# Automations = apps.get_model('email_messages', 'Messages') # < FAILS
class Message(models.Model):
name = models.CharField(max_length=100)
subject = models.CharField(max_length=128)
text = models.TextField()
account = models.ForeignKey(Account, on_delete=models.CASCADE)
date_created = models.DateTimeField(auto_now_add=True, null=True)
automations = models.ManyToManyField(Automation) # < PROBLEMATIC LINE
def __str__(self):
return self.name
I initially had this import from automations.models import Automation which caused this error:
ImportError: cannot import name 'Automation' from partially initialized module 'automations.models' (most likely due to a circular import)
But I no longer received that error after adding from automations.models import *. However, now I'm getting a definition error NameError: name 'Automation' is not defined when adding automations = models.ManyToManyField(Automation) to the Message class.
Does anyone know why is this happening? I just want to add a many:many relationship between classes Message & Automation (presumably a ManytoManyField(Class) field is needed to be added to both classes?).
I've read other posts with similar issues but could find no solution. Thanks
Warning!
I am not a professional and I am speaking just from minor experience. There might be a normal solution, but I have not yet found it!
I have stumbled upon this type of error and the reasoning behind it is very straight forward. The reason why you are unable to do this is that you need to be specific in these types of stuff. For example, to give a better perspective, imagine how would classes look like, when you want to model a family.
You might think of something like:
Mother, Father -> Child
Child -> Mother, Father
The problem is that this is not possible, since one of them HAS TO BE CREATED BEFORE THE OTHER ONE. This is the reason why you are getting a circular error.
Normally you would be able to create this, but from computer perspective, it needs to know how much memory it should allocate for the object, but because of the objects wants to be in each other, you will get something like this (in theory):
Allocate -> mother(childe(mother(child(....)), father(child(....)))) which I hope you can see would be an infinite cycle of allocating infinity.
To be even more specefic, what is python doing here is that it is trying to "copy-paste" everything you need right there where you have declared it. So what is happening here is that you said to it in file B -> import A and in A you have said import B which means to make it work, at the end, it needs to "copy-paste" itself on the place of import (so B -> import A -> import B => B -> imports B => impossible)
The only solution that at least I was able to find was something like this:
https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_many/ (Pay closer look on how its modeled)
The only way you can access the other object (lets say you have a publication and you want to know which articles have it in their M2M field) you have to search through the all articles when you want to know which articles have the publication.
Now to the second part of a question. Why it doesnt smash the circular error when you use import *. I personally think that the reason why is that python is interpreted language and it is doing alot of lazy loading in behind. What I mean by that is that it know when it seens import A -> import B -> import A, but when you introduce * there, the syntax check does not notice it ??? until it comes to the specific line. Similar types of errors can be seen when you use a wrong method name on a class and python notices it after it tries to call the mentioned method.
I am not that much sure with the second answer, yet I see this very often happen when I misstype the name of a fuction
So in other words, what you need to do:
Remove one of the imports, so you can clear the circular import problem (choose one, that fits more, like in the family example I have mentioned (it should be more clear which one should search for the other one))
Access the other part of M2M (in PSEUDOCODE !!!!):
Article.objects.filter(publication in publications)
Unfortunatelly I do not know the syntax by heart, but you can see where I am going with this (hopefully).
I hope it helps, if you have any questions, please go ahead and ask :)

Cyclic imports within django subapps

I'm working on a django project where i have the following setup
project
/products
/product1
/models.py
/forms.py
/productN
/otherapps
#models.py
from .forms import foo
...
#forms.py
from .models import bar
You see the cyclic imports. I've tried a number of combinations but i cant seem to get it right. I'd rather not move the code in forms.py to models.py
I've tried:
from products import *
from products.product1 import *
from products.product1.form import *
import products
import products.product1
import products.product1.form
Some help would be much appreciated.
In models.py move your
from .forms import foo
to inside the method that actually needs to use foo. This will stop it from importing until that method is called rather than as soon as models.py is imported. This isn't best practise and if you use foo in lots of places then it will be a pain to maintain but it should fix the circular import.

Python manage classes in separate files

I have a project which uses the MVC pattern.
In folder "models" I have quite many classes, each class is now has its own file. But I feel like it's not convenient, because every time I need to use a class I have to import it separately. E.g. I have many of the followings in my app source:
from models.classX import classX
from models.classY import classY
If I want to import everything at once, something like from models import * I found that I can put all sorts of import in models/__init__.py. But is it the pythonic way to do it ? What is the convention ?
Python is not java; please avoid the one-file-per-class pattern. If you can't change it, you can import all of them from a submodule of your models package:
# all.py: convenient import of all the needed classes
from models.classX import classX
from models.classY import classY
...
Then in your code you can write:
import my.package.models.all as models # or from my.package.models.all import *
and proceed to use models.classX, models.classY, etc.
Most pythonic way is one that you're already using. You can alleviate importing by grouping your classes in modules. For example, in Django usually all application models are in a single file.
From python docs:
Although certain modules are designed to export only names that follow certain patterns when you use import *, it is still considered bad practise in production code.
Firstly, you should rename your classes and modules so that they don't match, and follow PEP8:
models/
classx.py
class ClassX
classy.py
class ClassY
Then, I'd got with this in models/__init__.py:
from models.classx import ClassX
from models.classy import ClassY
Meaning in your main code, you can do any one of:
from models import *
x = ClassX()
from models import ClassX
x = ClassX()
import models
x = models.ClassX()

django: register listeners in models.py and cyclic import problems

I'm working on some signal listeners, which creates records from a model. And in django docs it is said listeners should be registered in models.py. Because the listeners are quite big in lines, I would like to separate their logics from the file of models.py. Seems like it's already causing cyclic importing problems in my case. What's the best way of avoiding this problem while keeping the codes separated?
currently it's like this:
models.py
class foo(models.Model):
#model definition
import listeners
listeners.py
import models
def fun(sender,**kwargs):
bar=models.foo()
#listener logics....
from AnotherApp.models import AnotherModel
post_save.connect(fun,sender=AnotherModel)
Here is a funny hack:
from django.db.models import get_model
import models
def fun(sender,**kwargs):
# still better than doing the import in the function isn't it ...
if sender != get_model('anotherapp', 'anothermodel'):
return
bar=models.foo()
#listener logics....
post_save.connect(fun)
And this might even work but i can't say:
post_save.connect(fun, sender=get_model('anotherapp', 'anothermodel'))
BTW, there are better names than listeners: reciever is the Django-ish name, and slot is the common name.
Anyhow, I can't be more helpful because I cannot reproduce your issue with the code you pasted. Please, make sure that you pasted code that is able to reproduce your issue.

Why would I put code in __init__.py files?

I am looking for what type of code would I put in __init__.py files and what are the best practices related to this. Or, is it a bad practice in general ?
Any reference to known documents that explain this is also very much appreciated.
Libraries and frameworks usually use initialization code in __init__.py files to neatly hide internal structure and provide a uniform interface to the user.
Let's take the example of Django forms module. Various functions and classes in forms module are defined in different files based on their classification.
forms/
__init__.py
extras/
...
fields.py
forms.py
widgets.py
...
Now if you were to create a form, you would have to know in which file each function is defined and your code to create a contact form will have to look something like this (which is incovenient and ugly).
class CommentForm(forms.forms.Form):
name = forms.fields.CharField()
url = forms.fields.URLField()
comment = forms.fields.CharField(widget=forms.widgets.Textarea)
Instead, in Django you can just refer to various widgets, forms, fields etc. directly from the forms namespace.
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)
How is this possible? To make this possible, Django adds the following statement to forms/__init__.py file which import all the widgets, forms, fields etc. into the forms namespace.
from widgets import *
from fields import *
from forms import *
from models import *
As you can see, this simplifies your life when creating the forms because now you don't have to worry about in where each function/class is defined and just use all of these directly from forms namespace. This is just one example but you can see examples like these in other frameworks and libraries.
One of the best practices in that area is to import all needed classes from your library (look at mongoengine, for example). So, a user of your library can do this:
from coollibrary import OneClass, SecondClass
instead of
from coollibrary.package import OneClass
from coollibrary.anotherpackage import SecondClass
Also, good practice is include in __init__.py version constant
For convenience: The other users will not need to know your functions' exactly location.
your_package/
__init__.py
file1.py/
file2.py/
...
fileN.py
# in __init__.py
from file1 import *
from file2 import *
...
from fileN import *
# in file1.py
def add():
pass
then others can call add() by
from your_package import add
without knowing file1, like
from your_package.file1 import add
Put something for initializing. For example, the logging(this should put in the top level):
import logging.config
logging.config.dictConfig(Your_logging_config)

Categories

Resources