I am pretty new to Django.
I wanted to create a form for some user information. Depending on type of user informations, the fields should change... For example the users private address needs the fields name, street, zip and city. But if he wants something send to the company, there might be more fields like department or company name.
I want to implement something like this and create for each kind of input an extra model compact in a separate app.
Is there a way to get a select field with a list of all available models in this app.
Edit
Since I have some further problems, I add an example here
file: experiment/models.py
from django.db import models
from django.apps import apps
class BasicExperiment(models.Model):
date_created = models.DateTimeField(editable=False)
date_modified = models.DateTimeField(blank=True)
label_app = apps.get_app('labels')
label_types = apps.get_models(label_app)
file: labels/models.py
from django.db import models
class SILAC(models.Model):
lys0 = models.BooleanField('Lys-0', default=True)
lys4 = models.BooleanField('Lys-4', default=None)
lys8 = models.BooleanField('Lys-8', default=None)
arg0 = models.BooleanField('Arg-0', default=True)
arg6 = models.BooleanField('Arg-6', default=None)
arg10 = models.BooleanField('Arg-10', default=None)
class Meta:
verbose_name = 'SILAC Labeling'
In the shell it works as expected:
>>> from django.apps import apps
>>> app = apps.get_app('labels')
>>> for model in apps.get_models(app):
... model._meta.verbose_name
...
'SILAC Labeling'
Within my models.py I get the following error:
...
File "/Users/madejung/Documents/django_dev/cfproteomics/experiments/models.py", line 5, in <module>
class BasicExperiment(models.Model):
File "/Users/madejung/Documents/django_dev/cfproteomics/experiments/models.py", line 10, in BasicExperiment
label_app = apps.get_app('labels')
File "/Library/Python/2.7/site-packages/django/apps/registry.py", line 370, in get_app
"App '%s' doesn't have a models module." % app_label)
django.core.exceptions.ImproperlyConfigured: App 'labels' doesn't have a models module.
You could try this:
from django.db.models import get_app, get_models
app = get_app('my_application_name')
for model in get_models(app):
# do something with the model
Here there is more information Django get list of models in application
Related
I'm getting a 'circular import' error when trying to makemigrations in Django. The two models in question are these. The error is being flagged on Team.
from django.db import models
from django.contrib.auth.models import User
from footballapi.models.team import Team
from footballapi.models.bio import Bio
class Player(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.ForeignKey(Bio, on_delete=models.CASCADE)
teams = models.ManyToManyField(Team, on_delete=models.CASCADE, related_name="members")
from django.db import models
from footballapi.models.player import Player
class Team(models.Model):
name = models.CharField(max_length=50)
roster_spot = models.ForeignKey(Player, on_delete=models.CASCADE)
I think the issue is with the ManyToManyField, and I keep reading that I should use a string instead of the import. But I've tried every combination of words and can't find the right string. What should it be? By the way, these models are all from the same app.
Besides the classes you can also use a string "app_name.model_name" for a foreignkey relationship thus avoiding to import each other.
teams = models.ManyToManyField("app_name.Team", on_delete=models.CASCADE, related_name="members")
Alternatively, you could change your datamodel with a through table in your m2m relationship. Using this table you could set a boolean indicating if a player is playing roster_post. Check out the docs: https://docs.djangoproject.com/en/4.1/ref/models/fields/#django.db.models.ManyToManyField.through
I have the following models in my models.py file in my django project
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
class CustomUser(AbstractUser):
pass
# add additional fields in here
class PDFForm(models.Model):
pdf_type=models.IntegerField(default=0)
pdf_name=models.CharField(max_length=100,default='')
file_path=models.FileField(default='')
class FormField(models.Model):
fk_pdf_id=models.ForeignKey('PDFForm', on_delete=models.CASCADE,default=0)
field_type=models.IntegerField(default=0)
field_page_number=models.IntegerField(default=0)
field_x=models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_y=models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_x_increment=models.DecimalField(max_digits=6,decimal_places=2,default=0)
class Meta:
ordering= ("field_page_number", "field_type")
class UserData(models.Model):
fk_user_id=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,default=0)
field_type=models.IntegerField(default=0)
field_text=models.CharField(max_length=200,default='')
field_date=models.DateField()
Here is how the models are related
1) a pdfform contains a pdf form and path for it on the file system
2) A pdfform has multiple FormFields in it. Each field has attributes, and the specific one under discussion is field_type
3)The UserData model has user's data, so one User can have multiple rows in this table. This model also has the field_type column.
What I am trying to query is to find out all rows present in the Userdata Model which are present in the FormField Model ( matched with field_type) and that are of a specific PDFForm.
Given that the Many to Many relationship in django models cannot happen between no unique fields, how would one go about making a query like below
select a.*, b.* from FormField a, UserData b where b.fk_user_id=1 and a.fk_pdf_id=3 and a.field_type=b.field_type
I have been going through the documentation with a fine toothed comb, but obviously have been missing how django creates joins. what is the way to make the above sql statement happen, so I get the required dataset?
I think UserData is missing a relation to FormField, but if you had this relation you could do:
UserData.objects.filter(
fk_user_id=1, # Rename this to user, Django wilt automicly create a user_id column
form_field__in=FormField.objects.filter(
fk_pdf_id=<your pdfid> # same as fk_user_id
)
)
Edit updated models
When you use a ForeignKey you don't have to specify the _id or default=0, if you don't always want to fill the field its better to set null=True and blank=True
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings
class CustomUser(AbstractUser):
pass
# add additional fields in here
class FieldTypeMixin:
TYPE_TEXT = 10
TYPE_DATE = 20
TYPE_CHOISES = [
(TYPE_TEXT, 'Text'),
(TYPE_DATE, 'Date'),
]
field_type=models.IntegerField(default=TYPE_TEXT, choises=TYPE_CHOISES)
class PDFForm(models.Model):
pdf_type = models.IntegerField(default=0)
pdf_name = models.CharField(max_length=100,default='')
file_path = models.FileField(default='')
class FormField(models.Model, FieldTypeMixin):
pdf_form = models.ForeignKey('PDFForm', on_delete=models.CASCADE)
field_page_number = models.IntegerField(default=0)
field_x = models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_y = models.DecimalField(max_digits=6,decimal_places=2,default=0)
field_x_increment = models.DecimalField(max_digits=6,decimal_places=2,default=0)
class Meta:
ordering = ("field_page_number", "field_type")
class SubmittedForm(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)
pdf_form = models.ForeignKey(PDFForm, models.CASCADE)
class SubmittedFormField(models.Model, FieldTypeMixin):
submitted_form = models.ForeignKey(SubmittedForm, models.CASCADE)
form_field = models.ForeignKey(FormField, models.CASCADE, related_name='fields')
field_text = models.CharField(max_length=200,default='')
field_date = models.DateField()
class Meta:
unique_together = [
['submitted_form', 'form_field']
]
I have models that uses UUID as its PK
class Foo(models.Model):
foo_id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False
)
tags = TaggableManager()
When I go and try to add a new tag
f = Foo.objects.latest('pk')
f.tags.add("testing")
I get DataError: integer out of range
When I import pdb on the cursor to view the SQL going in I see this.
(Pdb) params
(1, 287082253891563438098836942573405313042, 9)
(Pdb) sql
'INSERT INTO "taggit_taggeditem" ("tag_id", "object_id", "content_type_id") VALUES (%s, %s, %s) RETURNING "taggit_taggedit
m"."id"'
That long integer (287082253891563438098836942573405313042) trying to be insterted is obvsiouly the cause for the error. This number is the int of the UUID for foo_id
In [6]: foo.foo_id.int
Out[6]: 287082253891563438098836942573405313042
Is there something I can set to allow django-taggit to play nicely with contenttypes and UUID?
I'd like to extend #Pramod response, that was very helpful for me to find the right answer:
Taggit has another class that allows to change the behavior of the TaggedItem
Here is a snippet of how to implement this solution:
from django.db import models
from django.utils.translation import ugettext_lazy as _
from taggit.managers import TaggableManager
from taggit.models import GenericUUIDTaggedItemBase, TaggedItemBase
class UUIDTaggedItem(GenericUUIDTaggedItemBase, TaggedItemBase):
# If you only inherit GenericUUIDTaggedItemBase, you need to define
# a tag field. e.g.
# tag = models.ForeignKey(Tag, related_name="uuid_tagged_items", on_delete=models.CASCADE)
class Meta:
verbose_name = _("Tag")
verbose_name_plural = _("Tags")
class Food(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# ... fields here
tags = TaggableManager(through=UUIDTaggedItem)
source: http://django-taggit.readthedocs.io/en/latest/custom_tagging.html#genericuuidtaggeditembase
Here's an answer based on Austin's comment.
In django-taggit, references to tagged models are stored in a model named GenericTaggedItemBase under a field called object_id. The object_id field is hardcoded to models.IntegerField. So it's not possible to tag models having UUID primary keys. The code is located here.
If all your models that need to be tagged are of the same type (in this case, models.UUIDField), then you can set object_id's type to models.UUIDField.
Here are the changes that have to be made, assuming you're using virtualenvwrapper
Locate the taggit package in the site packages folder. ~/virtualenvs/<your_virtualenv>/lib/<python_version>/site-packages/taggit
Copy the taggit directory into your project.
Delete the taggit directory from site-packages
In the models.py file in taggit, replace
object_id = models.IntegerField(verbose_name=_('Object id'), db_index=True) with
object_id = models.UUIDField(verbose_name=_('Object id'), db_index=True)
Migrate taggit.
python manage.py makemigrations taggit
python manage.py migrate
I am doing a small blog in Mezzanine for learning purpose and wanted to add a custom content type by sub-classing "mezzanine.pages.models.Page" and registering this model with admin. My classes look something like this:
models.py:
from django.db import models
from mezzanine.pages.models import Page
class Student(Page):
dob = models.DateField("Date of birth")
name = models.CharField("Name", max_length=30)
gender = models.CharField("Gender", max_length = 5, choices=(('M','Male'),
('F','Female')), default = 'M')
image = models.ImageField(upload_to='Students')
class Project(models.Model):
student = models.ForeignKey("Student")
project_image = models.ImageField(upload_to="StudentProjects")
admin.py:
from copy import deepcopy
from django.contrib import admin
from mezzanine.pages.admin import PageAdmin
from .models import Student, Project
student_extra_fieldsets = ((None, {"fields": ("dob","name","gender","image")}),)
class ProjectInline(admin.TabularInline):
model = Project
class StudentAdmin(PageAdmin):
inlines = (ProjectInline,)
fieldsets = deepcopy(PageAdmin.fieldsets) + student_extra_fieldsets
admin.site.register(Student, StudentAdmin)
Now, when I visit "http://localhost:8000/admin/pages/page/" to add my newly registered content type, I get an empty option with no name, but when I select I get the Custom Content type "Student" Page to add and edit.
Since I have just started with Django and Mezzanine, I cannot simply figure it out.
I am using "sqlite" as backend and not using "South"
Any pointers to this??
Thanx for your help :)
I removed that "*name = models.CharField("Name", max_length=30)*" in models.py and replaced it with:
first_name = models.CharField("First Name", max_length=30)
last_name = models.CharField("Last Name", max_length=30)
And now every thing seems OK!!. (Only if I used "South"
I have an app name sync which has a form created from a model that saves itself. I want to create another app called activity that retrieves the data from the sync models and other future apps. How can I do that in the activity views app?
This is my sync models.py
from django.db import models
from django.contrib.auth.models import User
from django.forms import ModelForm
FS_CHOICES = (
('/path1/', 'P1'),
('/path2/', 'P2'),
('/path3/', 'P3'),
)
OPTIONS = (
('-n', 'TRY'),
)
class SyncJob(models.Model):
date = models.DateTimeField()
user = models.ForeignKey(User, unique=False)
source = models.CharField(max_length=3, choices=FS_CHOICES)
destination = models.CharField(max_length=3, choices=FS_CHOICES)
options = models.CharField(max_length=10, choices=OPTIONS)
class SyncJobForm(ModelForm):
class Meta:
model = SyncJob
fields = ['source', 'destination', 'options']
Ok, in activity views.py I have this:
from toolbox.sync.models import SyncJob
from django.shortcuts import render_to_response
def Activity()
sync_job = SyncJob.objects.get(id=03)
return render_to_response('base.html', {'sync_job': sync_job})
UPDATE: When I try to view the page it displays the error:
'function' object is not iterable
Just import it like any other python class.
So in your activity app you'd do something like this:
from sync.models import SyncJob
sync_job = SyncJob.objects.get(id=99)