Is there a snippet or easy way to import all of my django tables when entering the prompt?
For example, usually my commands go something like this:
>>> from userprofile.models import Table
>>> Table.objects...
This way, as soon as I entered the prompt, I'd already have the tables imported. Thank you.
django-extensions adds the shell_plus command for manage.py which does exactly this.
from django.db.models import get_models
for _class in get_models():
globals()[_class.__name__] = _class
Here you end up with all installed models available globally, refering to them with their class name. Read the docs for django.db.models.get_models for more info:
Definition: get_models(self, app_mod=None, include_auto_created=False, include_deferred=False)
Docstring:
Given a module containing models, returns a list of the models.
Otherwise returns a list of all installed models.
By default, auto-created models (i.e., m2m models without an
explicit intermediate table) are not included. However, if you
specify include_auto_created=True, they will be.
By default, models created to satisfy deferred attribute
queries are not included in the list of models. However, if
you specify include_deferred, they will be.
You can do this:
>>> from django.conf import settings
>>> for app in settings.INSTALLED_APPS:
... module = __import__(app)
... globals()[module.__name__] = module
...
You'll get the fully qualified names though; userprofile.models.Table instead of Table.
Related
I'm creating a simple script used to generate fixture data for a given django model. I cannot figure out how to create an import statement which accepts user input, to allow me to perform the actual logic on the selected model.
I've tried various combinations of imp, importlib.util.spec_from_file_location,
importlib.import_module,
__import__,
Create an import statement using variable "interpolation"
The closest I've gotten is:
def import_function(app, model):
exec(f"from {app}.models import {model}")
exec(f"print({model}.objects.all())") #This works.
import_function("home", "Person")
My thinking is: I create a module called 'fixture.py'. Within that module is a custom import function. I import the module into the environment created by
python manage.py shell so as to obviate the need for modifying the PATH.
Then, I call the function using fixture.import_function(app, model).
I've managed to generate the fixture data this way, but only when I'm hardcoding the import statement, i.e. from home.models import Person.
#fixture generating logic.
This is the wrong approach. There's no need to fiddle with imports or construct names dynamically. Use the functions that Django provides to find the model:
from django.apps import apps
model = apps.get_model(app, model)
print(model.objects.all())
I am currently on Django 1.7 and my database is PostgreSQL. I have the following model.
# myapp/models.py
from django.db import models
from json_field import JSONField # using django-json-field
from json_field.fields import JSONDecoder
class MyModel(models.Model):
the_data = JSONField(
decoder_kwargs={'cls': JSONDecoder, 'parse_float': float},
default='[{}]',
)
...
I am now looking to upgrade to Django 1.10 and take advantage of the new(ish) JSONField in django.contrib.postgres.fields.
I change my model to look like this.
# myapp/models.py
from django.db import models
from django.contrib.postgres.fields import JSONField # Now want to use the new JSONField
class MyModel(models.Model):
the_data = JSONField(
default='{}',
)
...
I then create a migration for the app.
./manage.py makemigrations myapp
When it attempts to create a migration it complains...
from json_field.forms import JSONFormField
File "/Users/travismillward/Projects/amcards_env/lib/python2.7/site-packages/json_field/forms.py", line 5, in <module>
from django.forms import fields, util
ImportError: cannot import name util
I understand why it is complaining. django-json-field is not updated for django 1.10 and it wants to import json_field in one of the original migration files. So I can either go back and modify my original migration file that imports json_field but then it won't actually modify the column data type because it thinks it is already done. Or, I have to fix django-json-fields to work with django 1.10 just so the migration can be created. And I will have to leave that requirement in place even though I don't use it, it's just for the migration!
On my last project I just modified the original migration to make it think that it was using django.contrib.postgres.fields.jsonb.JSONField all along. However, after I ran the migration, it didn't change the column's data type from text to jsonb. So I manually did that since it was a smaller project. For this project, I really don't want to manually alter the database.
Any suggestions on how to migrate away from django-json-field gracefully and with a plan to remove it from my code and requirements?
I have myApp/models/profiles.py instead of myApp/models.py (to group related models)
How do you set AUTH_USER_MODEL in this case?
Because auth accepts only "foo.bar" pattern.
app_label, model_name = settings.AUTH_USER_MODEL.split('.')
Django expects the models for any given app to be in app.models. If you want to use this kind of file structure, you'll need to still make sure this is the case. The easiest way to do this is too add from profiles import * in myApp/models/__init__.py and then use AUTH_USER_MODEL as normal.
For example, you you had myApp/models/profiles.py and myApp/models/actions.py your myApp/models/__init__.py should read
from profiles import *
from actions import *
Remember to make sure you don't have any name conflicts too, and you may wish to use set your __all__ value in each of your sub-packages.
You can either pass the class directly or the 'app.model'. django only registers classes defined in app.models module, so you'll need to import the class in models init. Since you'll be importing the model in init anyway, you don't need to specify the full path to the class in the foreignkey.
I'm getting started with Django. I can't get the admin to work (it used to work, I'm not sure what update made it break...).
As soon as I register a model in the admin, the website crashes with this error on any URL:
'module' object is not iterable
In the trace it happens to bug on this:
/Library/Python/2.7/site-packages/django/contrib/admin/sites.py in register
for model in model_or_iterable:
admin_class
<class 'django.contrib.admin.options.ModelAdmin'>
options
{}
model_or_iterable
<module 'model.Branch' from '...../farmpower/src/model/Branch.pyc'>
self
<django.contrib.admin.sites.AdminSite object at 0x1098196d0>
I've tried with different models, in that example, with Branch (code in admin.py):
from django.contrib import admin
from models import *
admin.site.register(Branch)
models.py:
import Page, Promotion, Branch, Contact
Branch.py
from django.db import models
from django.utils.translation import ugettext_lazy as _
class Branch(models.Model):
name = models.CharField
[...]
class Meta:
app_label = "model"
db_table = "cms_branch"
def __unicode__(self):
return self.name
Thank you for your help !
There are several things in your code that are not very neat. One of them might lead to the error you're seeing, though I don't know which one of 'em is it.
You use relative imports (from models import ...). It is more robust do do an absolute import like from yourapp.models import ...).
You use a "star import": from models import *. You don't really know what you're importing exactly in the file where you're doing this. Also automatic code checkers (like pyflakes) cannot check whether you're missing imports anymore.
You mention models.yml as the filename. That's not a .py extension, so python doesn't do a thing with that one.
The app name you set in the Meta on your models is model. Note that "models" and "model" are quite django-internal names. So having an app called "model" with a "models.py" could easily go wrong. Why is the app not yourapp or something like that?
Here are some ways in which it could go wrong:
Star import: perhaps you've imported a different admin in models.py? Which overwrites, through the star import, the one in admin.py?
The models.yml: if that really is the name, what does from models import * return? With a non-existing models.py? Try to import Branch explicitly: from models import Branch and see if it fails.
App name: if your app is really called "model", a relative import from models import * could perhaps get you the top-level "model" module instead of the "model.models" that you mean in case you mis-type something.
It's your
from models import *
it should be
from appName.models import className
Django dumpdata command is broken because it does not support any reasonable way to narrow down the amount of data dumped. I need to create a fixture of various querysets (and I don't need to take care about dumping objects from outer models relations). Limiting the number of items for those querysets, like django-test-utils makefixture does is not sufficient. Tried to achieve this by using a proxy model with custom manager, but this approach does not work - dumpdata ommits proxy models (which is reasonable).
If dumpdata doesn't work, you can do the same through Django Serializing data.
from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all())
and then write the data on a file.
The following steps will help in making the solution complete providing support to create a fixture of various querysets.
from django.core import serializers
from django.core.management.commands.dumpdata import sort_dependencies
app_list = {}
# Add all your querysets here. The key for the dictionary can be just a
# unique dummy string (A safe hack after reading django code)
app_list['app1_name'] = FirstModel.objects.all()
app_list['app2_name'] = SecondModel.objects.all()
# The sort_dependencies will ensure that the models are sorted so that
# those with foreign keys are taken care. If SecondModel has a fk to FirstModel,
# then sort_dependencies will take care of the ordering in the json file so that
# FirstModel comes first in the fixture thus preventing ambiguity when reloading
data = serializers.serialize("json", sort_dependencies(app_list.items()))
f = open('output.json', 'w')
f.write(data)
f.close()
Now the output will be available in output.json file. To rebuild the models from the json file:
from django.core import serializers
for obj in serializers.deserialize('json', open('output.json').read()):
obj.save()
EDIT: Strangely, the sort_dependencies didn't work as expected. So I ended up using python ordereddict and decided the order myself.
import collections
app_list = collections.OrderedDict()
In case you want to save json data directly to a file, you can use:
from django.core import serializers
data = YourModel.objects.all()
with open("fixtures.json", "w") as out:
serializers.serialize("json", data, stream=out)
I'm not sure what you mean by "outer models relations", maybe an example would help, but you can pass dumpdata the model you're interested in...
manage.py dumpdata --help
Usage: ./manage.py dumpdata [options] [appname appname.ModelName ...]
and there's the exclude switch:
-e EXCLUDE, --exclude=EXCLUDE
An appname or appname.ModelName to exclude (use
multiple --exclude to exclude multiple apps/models).