My old structure used to be like this:
models.py
class Model1
class Model2
...
I have since moved this to
modelsdir
__init__.py
model1.py
class Model1
model2.py
class Model2
models.py
from modelsdir.model1 import Model1
from modelsdir.model2 import Model2
After this change, makemigraitons and makemigrations myapp no longer detect any changes done on the models. Any idea how to fix this?
EDIT:
I have since moved to this: removed models.py and renamed modelsdir to models
now it looks like so:
models
__init__.py
from .model1 import Model1
from .model2 import Model2
model1.py
model2.py
Unfortunately this still doesn't detect any changes.
I have a django project that is structured this way, and I had to add this in my modelsdir/__init__.py file:
from .model1 import *
from .model2 import *
I also didn't keep the original models.py file in my top-level app folder.
This is on Django 1.10/1.11 and Python 3.
Related
I am trying to import a model class from another app. My structure looks like the following:
mysite/
-- main/
models.py
-- webshop/
models.py
I'd like to import a model class from my webshop app into the main/models.py. I run the following in my main/models.py file:
from django.db import models
from ..webshop.models import Item
# Create your models here.
class Test(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
In my text editor everything seems fine. It finds the appropriate app and finds the model class Item which I need to import there.
When I run makemigrations I am getting the following error:
ValueError: attempted relative import beyond top-level package
I've read some other questions on SO on how to make this work but can't figure it out. Tried:
mysite.webshop.models import Item
aswell. But then I get a: ModuleNotFoundError: No module named 'mysite.webshop'.
Does anyone have suggestions?
From the error ValueError: attempted relative import beyond top-level package, I'm going to assume in your text editor, your current working directory is mysite/. And so using ..webshop.models you're trying to go up two directories above mysite/ which is why you're getting the error.
What you need to do is:
from django.db import models
from webshop.models import Item
after customizing django oscar app (address) and adding a new field named 'area' when I run migrate it gave me Unknown field(s) (area) specified for UserAddress
I used the command
./manage.py oscar_fork_app address myappsfolder/
after creating the folder and __init__.py file in it
then I started to customize the app like this:
#myappsfolder/address/models.py
from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from oscar.apps.address.abstract_models import AbstractAddress
class Address(AbstractAddress):
area = models.CharField(_("Area"), max_length=120,
choices=settings.AREA_CHOICES, blank=True)
from oscar.apps.address.models import *
#myappsfolder/address/forms.py
from oscar.apps.address import forms as base_forms
class UserAddressForm(base_forms.UserAddressForm):
class Meta(base_forms.UserAddressForm.Meta):
fields = ['area']
I didn't touch the admin.py , config.py and __init__.py that have been created by the command ./manage.py oscar_fork_app address myappsfolder/
also the __init__.py that I created in myappsfolder is empty, should I add something to these files ?
What should I do to customize this app ? or any other app ?
If I edited the models in oscar/apps/address/abstract_models.py it only apply in local host and the error in forms disappear , which means that django still reading the models from oscar/apps not from myappsfolder.
You cannot override AbstractAddress in that way because the changes will not propagate to other models such as UserAddress that directly subclass AbstractAddress. Instead you need to override the specific address models that you want to change. So if you want to change UserAddress then override that particular model:
from oscar.apps.address.abstract_models import AbstractUserAddress
class UserAddress(AbstractUserAddress):
area = models.CharField(_("Area"), max_length=120, choices=settings.AREA_CHOICES, blank=True)
... after which your changes to UserAddressForm should work.
If you need to override ShippingAddress as well, then you will also have to fork the shipping app and do the same thing there, because that is where the model lives.
I understand that if I want to establish a foreign key relationship for this model:
class MyModel(models.Model):
pass
... from this location
/myproject
/myapp
models.py (MyModel)
... I can use a "string-named" relationship to avoid import-time errors.
# this is in a different app within myproject
class DependentModel(models.Model):
my_model = models.ForeignKey('mayapp.MyModel')
But how do I establish that same ForeignKey relationship with a string when my models have been distributed across a models dir (e.g. not contained within one models.py file)
/myproject
/myapp
/models
/one.py (MyModel)
/two.py (other models)
(Assume that I can't just import the model directly, ala from myapp.models.one import MyModel)
Aha! I should have taken just a couple more minutes to search; this is possible simply by importing your models from within the __init__.py file inside the models dir:
# myproject/myapp/models/__init__.py
from one import MyModel
Related question: How do I separate my models out in django?
I've got a weird problem.
I am building a Flask app with SQLAlchemy. I have a file with models, namely, models.py. And I have a User model there.
If I open my "views.py" and insert a string
import models
and then use the User model like
u=models.User.query.filter_by(name='John',password='Doe').first()
everything works fine.
But if instead of "import models" i put
from models import User
Python crashes and says:
ImportError: cannot import name User
how can this be possible?
you most likely have a circular import; your, lets say 'app' module:
# app.py
import models
...
def doSomething():
models.User....
but your models module also imports app
import app
class User:
...
since models imports app, and app imports models, python has not finished importing models at the point app tries to import models.User; the User class has not been defined (yet). Either break the cyclic import (make sure models doesn't import anything that also imports models), or you'll just have to make do with models.User instead of the shorter User in app.
Instead of
from models import User
use
from models import *
In this case, you are importing the models into views.py therefore if you need a class from models, import it from views.py and the circular import problem will be resolved.
Currently all my models are in models.py. Ist becomming very messy.
Can i have the separate file like base_models.py so that i put my main models there which i don't want to touch
Also same case for views and put in separate folder rather than develop a new app
Yes, it's doable. It's not particularly pretty though:
make models a module, so your directory structure looks like this:
- models
|- __init__.py
|- some_model.py
|- some_other_model.py
|- ...
now, the magic lies in __init__.py and some little extras in the models. __init__.py:
from some_model import SomeModel
from some_other_model import SomeOtherModel
__all__ = [
'SomeModel',
'SomeOtherModel',
]
some_model.py:
class SomeModel(models.Model):
class Meta(object):
app_label = 'yourapplabel'
db_table = 'yourapplabel_somemodel'
Everything acjohnson55 said, plus the fact that you need to specify the app_label attribute in each model's Meta class.
A link to an actual example on github:
https://github.com/stefanfoulis/django-filer/tree/develop/filer/models
you can separate the model file like this :
-------models/
-------------- init.py
-------------- usermodels.py
--------------othermodel.py
in the init.py:
---------------from usermodels import *
---------------from othermodel import *
and in the *models.py , add META class:
--------class Meta:
--------------app_label = 'appName'
Yes, just make a folder called models and in that folder put all of your separated model files. You need to put a file called __init__.py in the models folder for it to be considered the models module. In __init__.py, use from ... import ... to put the names you want available directly in yourapp.models, otherwise you will have to import them as yourapp.models.base_model, or whatever submodule name you use.
Also, in each model, you will have to add a Meta attribute called app_label = 'yourapp' to make sure your models are recognized as part of the app.
This is how I normally do it:
# Folder structure:
#==================
# models/
# __init__.py
# products.py
# stocks.py
# In init.py (don't forget the period before model file name)
#===========
from .products import Product
from .stocks import Stock
__all__ = [
'Product',
'Stock',
]
# And run "py manage.py makemigrations" and "py manage.py migrate" as normal