In my Django model I created a custom field called LocationField following this tutorial Django admin Google Maps.
Now my problem is migration using south doesnt seem to be working. It gave me an error
! Cannot freeze field 'SilverInningsHelpline.classified.location'
! (this field has class SilverInningsHelpline.widgets.LocationField)
! South cannot introspect some fields; this is probably because they are custom
! fields. If they worked in 0.6 or below, this is because we have removed the
! models parser (it often broke things).
! To fix this, read http://south.aeracode.org/wiki/MyFieldsDontWork
To fix this, I added the inspection rules as defined by the documentation of South as follows:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([
(
[Classified],
[],
{
"location": ["LocationField", {"blank": "true"}]
}
)
], ["^southut\.fields\.Classified"])
where Classified model contains the LocationField. My classified model is as follows:
class Classified(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=256)
contact_person = models.CharField(max_length=300)
email = models.CharField(max_length=100)
address = models.ForeignKey(Address)
subcategory = models.ForeignKey(Subcategory)
phone_number = models.BigIntegerField(max_length=20, default=0)
secondary_number = models.BigIntegerField(max_length=20, default=0, blank=True)
more_numbers = models.CharField(max_length=300, default='', blank=True)
image = S3DirectField(upload_to='s3direct', blank=True)
description = models.TextField(max_length=1000, blank=True)
location = LocationField(blank=True, max_length=255)
Any suggestions to fix this would be massively appreciated.
It looks like you didn't bother to read the doc.
You're passing your model class (Classified) where add_instrospection_rules expects your field class (LocationField).
The 'keyword arguments' dict is supposed to describe which keyword args your field expects, not a description of how your field is used in a given model class
The qualified field name pattern at the end should match your field's qualified name, not some random mumbo jumbo combination of what's in the tutorial and your model class name.
Related
Imagine I have some models as below:
class User(AbstractUser):
pass
class Medium(models.Model):
researcher = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True, related_name="medium_researcher")
old_medium_name = models.CharField(max_length=20, null=True, blank=True)
class Uptake(models.Model):
material_quality = models.CharField(max_length=20, null=True, blank=True)
medium = models.ForeignKey(Medium, on_delete=models.CASCADE, blank=True, null=True, related_name="uptake_medium")
Now I have a function to return all column names to generate some overview in my HTML as such:
from database.models import Medium
MODEL_HEADERS=[f.name for f in Medium._meta.get_fields()]
MODEL_HEADERS
['uptake_medium', 'id', 'researcher', 'old_medium_name']
Why does this return uptake_medium? As this is a ForeignKey relation set within the Uptake model, it should only be present within the Uptake model right? When I review the admin models this column does not show up, neither in the db.sqlite3 model when checking Uptake, so it seems to be sort of hidden, and only show up when requested with _meta. The relationship seems to be correct... This is causing a lot of problems with my code, and it would be great if only the 'non-meta' columns only could be returned. How should I approach?
Why does this return uptake_medium? As this is a ForeignKey relation set within the Uptake model, it should only be present within the Uptake model right?
You can access the relation in reverse, for example:
my_medium.uptake_medium.all()
to obtain all Updates related to the Medium instance named medium.
You can also filter on that field, for example:
Medium.objects.filter(uptake_medium__material_quantity=42)
hence it is accessible just like any field.
You can filter with:
from django.db.models.fields.reverse_related import ManyToOneRel
[f.name for f in Medium._meta.get_fields() if not isinstance(f, ManyToOneRel)]
I'm writing a rather simple REST API using Django REST Framework. I am trying to add a boolean field to my model that would show if it is publicly accessible or not.
In my models.py, my model looks like this:
class BlogPost(models.Model):
title = models.CharField(max_length=20, default='', blank=False)
description = models.CharField(max_length=140, default='', blank=False)
is_public = models.BooleanField(default=True, blank=False)
Then in my serializers.py, my serializer for the model looks like this:
class BlogPostSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
fields = ('title', 'description', 'is_public')
However, when I create an instance of that model, and run my development server, the JSON only returns the title and the description. The is_public field is missing from the JSON.
I've searched everywhere and can't find the reason for this odd problem.
Any help would be much appreciated!
I am little bit comfused. Lets say I have such models.
models.py:
class Company(models.Model):
name = models.CharField(blank=False, null=False)
class Game(models.Model):
developer = models.ForeignKey(Company, on_delete=models.CASCADE)
publishers = models.ManyToManyField(Company)
If I use next code:
current_company = Company.object.get(pk=1)
current_company.game_set.all()
as I understand it return all games of current_company, but what field (developer or publishers) Django used?
But this code wouldn't be valid, for precisely this reason. If you tried to run it, Django would tell you that there was a conflict in the reverse relation.
If you have two relationships pointing to the same model, you need to explicitly set related_name on one of them to avoid this conflict.
I am using Django REST Framework. I have two models, Sites and Statuses.
class Sites(models.Model):
site_id = models.AutoField(primary_key=True)
status = models.ForeignKey(Statuses, models.DO_NOTHING, blank=True, null=True)
class Statuses(models.Model):
status_id = models.AutoField(primary_key=True)
description = models.CharField(max_length=255, blank=True, null=True, unique=True)
class Meta:
managed = True
db_table = 'Statuses'
I would like to be able to perform a GET on sites, and have the Statuses.description field returned (instead of Statuses.status_id). Also, I would like it so that either status_id or description may be used interchangeably in a POST to create a new site. Where does this type of functionality belong (serializer, models, etc...)?
I know I can accomplish the first part of my question by adding a property to the Sites model and then referencing this field in the Sites serializer.
#property
def status(self):
return self.row_status.description
However I thought the convention of a Model is that it should be a 1:1 representation of the database table. Is there a better way to do this?
This fits well in the serializer, like this:
class SitesSerializer(serializers.ModelSerializer):
description = serializers.CharField(source='status.description')
class Meta:
model = Sites
fields = ('site_id', 'description')
(But the status field should probably not have null=True set.)
I am just starting with Django and want to create a model for an application.
I find Djangos feature to
- automatically define validations and html widget types for forms according to the field type defined in the model and
- define a choice set for the field right in the model
very usefull and I want to make best use of it. Also, I want to make best use of the admin interface.
However, what if I want to allow the user of the application to add fields to the model? For example, consider a simple adress book. I want the user to be able to define additional atributes for all of his contacts in the admin settings, i.e. add a fax number field, so that a fax number can be added to all contacts.
from a relational DB perspective, I would have a table with atributes (PK: atr_ID, atr_name, atr_type) and an N:N relation between atributes and contacts with foreign keys from atributes and contacts - i.e. it would result in 3 tables in the DB. right?
but that way I cannot define the field types directly in the Django model. Now what is best practice here? How can I make use of Djangos functionality AND allow the user to add aditional/custom fields via the admin interface?
Thank you! :)
Best
Teconomix
i would suggest storing json as a string in the database, that way it can be as extendable as you want and the field list can go very long.
Edit:
If you are using other damn backends you can use Django-jsonfield. If you are using Postgres then it has a native jsonfield support for enhanced querying, etc.
Edit 2:
Using django mongodb connector can also help.
I've used this approach, first seen in django-payslip, to allow for extendable fields. This provides a structure for adding fields to models, from which you can allow users to add/edit through standard view procedures (no admin hacking necessary). This should be enough to get you started, and taking a look at django-payslip's source code (see the views) also provides view Mixins and forms as an example of how to render to users.
class YourModel(models.Model):
extra_fields = models.ManyToManyField(
'your_app.ExtraField',
verbose_name=_('Extra fields'),
blank=True, null=True,
)
class ExtraFieldType(models.Model):
"""
Model to create custom information holders.
:name: Name of the attribute.
:description: Description of the attribute.
:model: Can be set in order to allow the use of only one model.
:fixed_values: Can transform related exta fields into choices.
"""
name = models.CharField(
max_length=100,
verbose_name=_('Name'),
)
description = models.CharField(
max_length=100,
blank=True, null=True,
verbose_name=_('Description'),
)
model = models.CharField(
max_length=10,
choices=(
('YourModel', 'YourModel'),
('AnotherModel', 'AnotherModel'), # which models do you want to add extra fields to?
),
verbose_name=_('Model'),
blank=True, null=True,
)
fixed_values = models.BooleanField(
default=False,
verbose_name=_('Fixed values'),
)
class Meta:
ordering = ['name', ]
def __unicode__(self):
return '{0}'.format(self.name)
class ExtraField(models.Model):
"""
Model to create custom fields.
:field_type: Connection to the field type.
:value: Current value of this extra field.
"""
field_type = models.ForeignKey(
'your_app.ExtraFieldType',
verbose_name=_('Field type'),
related_name='extra_fields',
help_text=_('Only field types with fixed values can be chosen to add'
' global values.'),
)
value = models.CharField(
max_length=200,
verbose_name=_('Value'),
)
class Meta:
ordering = ['field_type__name', ]
def __unicode__(self):
return '{0} ({1}) - {2}'.format(
self.field_type, self.field_type.get_model_display() or 'general',
self.value)
You can use InlineModelAdmin objects. It should be something like:
#models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100)
class ContactType(models.Model):
name = models.CharField(max_length=100)
class Contact(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
contact_type = models.ForeignKey(ContactType, on_delete=models.CASCADE)
value = models.CharField(max_length=100)
#admin.py
from django.contrib import admin
class ContactInline(admin.TabularInline):
model = Contact
class PersonAdmin(admin.ModelAdmin):
inlines = [
ContactInline,
]
By the way... stackoverflow questions should contain some code. You should try to do something before asking a question.