Django-import-export problem importing foreignkey field - python

I am using the Django-import-export(version 2.5.0) module in Django(version 3.1.4). So I am able to import all my models fields except for the ForeignKey field. I don't know how to make this one work. Can you look at my code and see what is wrong or needs to change? I need Django Admin to import the ForeignKey field.
models.py
# myapp
from django.db import models
from django.contrib.auth.models import User
class Agency(models.Model):
system_name = models.CharField(max_length=255)
county = models.CharField(max_length=60)
state = models.CharField(max_length=2)
active = models.BooleanField(default=True)
system_no = models.CharField(max_length=7, unique=True)
def __str__(self):
return self.system_no
class SitePart(models.Model):
# I tried changing the "system_no" to another name "agency_no" through out the *.py's this did not resolve the problem. Maybe I missed something.
system_no = models.ForeignKey('Agency', on_delete=models.CASCADE, to_field='system_no', null=True, blank=True)
part_name = models.CharField(max_length=125)
status_tuple = [('AB','Abandoned'),('AC','Active Compliant'),('DS','Destroyed'),('IA','Inactive'),
('SB','Stand By waiting acitvation'),('MO','Monitoring')]
status = models.CharField(max_length=2, choices=status_tuple, default= 'SB')
# sys_site_n is unique
sys_site_n = models.CharField(max_length=15, unique=True)
def __str__(self):
return self.part_name
resources.py
from import_export import fields, resources, widgets
from import_export.widgets import ForeignKeyWidget
from myapp.models import Agency, SitePart
class AgencyResource(resources.ModelResource):
class Meta:
model = Agency
import_id_fields = ('system_no',)
fields = ('system_name', 'county', 'state', 'active', 'system_no',)
class SitePartResource(resources.ModelResource):
system_no = fields.Field(
column_name='system_no',
attribute='system_no',
widget=ForeignKeyWidget(Agency,'system_no'))
print(system_no)
class Meta:
model = SitePart
import_id_fields = ('sys_site_n',)
fields = ('system_no','part_name','status', 'sys_site_n',)
admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from myapp.resources import AgencyResource, SitePartResource
from myapp.models import (Agency, County, SitePart)
class AgencyAdmin(ImportExportModelAdmin):
resource_class = AgencyResource
list_display = ('system_name', 'county', 'state', 'active', 'system_no',)
class SitePartAdmin(ImportExportModelAdmin):
list_display = ('system_no', 'part_name', 'status', 'sys_site_n',)
search_fields = ['system_no',] # Tried removing this, didn't work
resource_class = SitePartResource
admin.site.register(Agency, AgencyAdmin)
admin.site.register(County)
admin.site.register(SitePart, SitePartAdmin)
Agency Table
system_name
county
state
active
system_no
MAGNA SCHOOL
INYO
CA
1
1300553
PINE SCHOOL
INYO
CA
1
1300560
SitePart Table
system_no
part_name
status
sys_site_n
1300553
MAGNA SCHOOL
AC
1300553-01
1300553
Backup Genrtor
SB
1300553-02
1300560
PINE SCHOOL
AC
1300560-01
1300560
Backup Genrtor
SB
1300560-02
When I do import in django admin the system_no is empty.

I don't have the reputation points to be able to add a comment but I think the issue you're experencing is due to your model's field naming conventions.
Since your foreign key relation inside the SitePart to Agency is called system_no, your SitePartResource's ForeignKey Widget isn't referencing the correct field - it's referencing the related Agency model instance (which I believe is why you aren't getting any errors on import but the value is not being displayed).
To fix this, you just neeed to change the ForeignKey widget to reference the related Agency object's system_no field (not the instance itself). I haven't tested it but changing your FK field to something like the following should work!
#resources.py
class SitePartResource(resources.ModelResource):
...
system_no = fields.Field(
column_name='system_no',
attribute='system_no',
widget=ForeignKeyWidget(
Agency,
field='system_no__system_no'
)
)
...
EDIT:
#resources.py
class SitePartResource(resources.ModelResource):
class AgencyForeignKeyWiget(ForeignKeyWidget):
def get_queryset(self, value, row):
return self.model.objects.filter(
system_no__exact=row["system_no"],
)
system_no = fields.Field(
column_name='system_no',
attribute='system_no',
widget=AgencyForeignKeyWidget(
Agency,
field='system_no'
)
)
part_name = fields.Field(column_name="part_name", attribute="part_name")
status = fields.Field(column_name="part_name", attribute="part_name")
sys_site_n = fields.Field(column_name="system_site_n", attribute="system_site_n")
class Meta:
model = SitePart
import_id_fields = ("system_no", "system_site_n")
fields = ('system_no','part_name','status', 'sys_site_n',)

Related

Modelchoicefield save in database django

I want to create a webapp for managing a library .i create the book and the category model.the category is the class of the book 'history literature ..ect' ,i want the category appears as options when adding the book .so i put it in ModelChoiceField,but when i try to save the value of ModelChoiceField in database, it does not.
here is the code.
models.py
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=100)
class Livre(models.Model):
titre = models.CharField(max_length=30,null=True)
category=models.CharField(max_length=30,null=True)
num_category=models.ForeignKey(Category, on_delete=models.CASCADE,null=True)
auteur=models.CharField(max_length=30,null=True)
nombre_copie=models.IntegerField(default=0,null=True)
publisher=models.CharField(max_length=30,null=True)
forms.py
from django import forms
from . import models
from project.models import Category
class Ajouterlivre(forms.Form):
titre = forms.CharField(max_length=100)
category = forms.ModelChoiceField(queryset=Category.objects.values_list('name', flat=True))
auteur = forms.CharField(max_length=100)
nombre_copie = forms.IntegerField()
publisher = forms.CharField(max_length=100)
views.py
def Ajoutlivre(request):
if request.method== 'POST':
form=forms.Ajouterlivre(request.POST)
if form.is_valid():
objt=Livre()
objt.titre = form.cleaned_data['titre']
objt.category= form.cleaned_data['category']
objt.auteur = form.cleaned_data['auteur']
objt.nombre_copie = form.cleaned_data['nombre_copie']
objt.publisher = form.cleaned_data['publisher']
objt.save()
return redirect('home')
else:
form=forms.Ajouterlivre()
return render(request,'livre/ajout-livre.html',{'form':form})
ModelchoiceField requires queryset returning dictionary and not tuples, when you use values_list its returns a tuples.
so you have to change the category (**) line in your code to work.
class Ajouterlivre(forms.Form):
titre = forms.CharField(max_length=100)
**category = forms.ModelChoiceField(queryset=Category.objects.all())**
auteur = forms.CharField(max_length=100)
nombre_copie = forms.IntegerField()
publisher = forms.CharField(max_length=100)
Hope this solves your problem.

Django: 'Country' object has no attribute 'all'

Whenever I try to access my model "Youtube" from django admin, it shows me this error. I am sensing I have messed it up in the YoutubeAdmin, inside the getCountry method. How can I solve this? Cannot find a way. It says model Youtube doesn't have a filed getCountry in the error.
My model :
class Youtube(models.Model):
link = models.CharField(max_length=2000)
scrap_interval_hour = models.IntegerField(default=8)
last_scrapped_datetime = models.DateTimeField(blank=True, null=True)
is_feed = models.BooleanField(default=False)
created_date = models.DateField(
auto_now_add=True)
# Foriegn Key
country = models.ForeignKey(Country, on_delete=models.CASCADE)
class Meta:
ordering = ('created_date', )
admin
from django.contrib import admin
from fpn.models import Youtube
from datetime import timedelta
class YoutubeAdmin(admin.ModelAdmin):
def get_fields(self, request, youtube=None):
fields = super(YoutubeAdmin, self).get_fields(request, youtube)
fields.remove('last_scrapped_datetime')
if youtube:
fields.remove('country')
return fields
model = Youtube
list_per_page = 10
list_display = ('link', 'is_feed',
'getCountry', 'last_scrapped_datetime')
list_filter = ('country', 'is_feed', )
def getCountry(self, obj):
return "\n".join([coun.name for coun in obj.country.all()])
ForeignKey create many-to-one relation. This mean for one country you can have many Youtube objects. But not reverse, one Youtube object can have only one country.
So in your case you cannot query list of countries from youtube object. Since it has only one related country which you can access directly:
def getCountry(self, obj):
return obj.country.name

Django Models - How do you add subtype choice when user selects choice?

I'm working on a project where they have various job types that I've tackled with CHOICES, however, I want to add conditionals for WHEN job type 1 is chosen, SUBTYPES x-y become choices. I am having trouble with the syntax of how you would do that. I've included my pseudocode below... I appreciate any help!
from django.db import models
class User(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Job(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='jobs')
JOB_CHOICES = (
('carpentry', 'Carpentry'),
('cleaning', 'Cleaning'),
('electrician', 'Electrician'),
('handyman', 'Handyman'),
('hvac', 'HVAC'),
('painting', 'Painting'),
('pest', 'Pest'),
('plumbing', 'Plumbing'),
('roofing', 'Roofing'),
('property', 'Property'),
)
jobType = models.CharField(max_length=30, choices=JOB_CHOICES, default='handyman')
# If JobType = Carpentry:
# CARPENTRY_CHOICES = (
# ('trim', 'trim')
# ('sheetrock', 'Sheetrock')
# ('windows', 'Windows')
# ('doors', 'Doors')
# ('cabinets and shelving', 'Cabinets and Shelving')
# ('other', 'Other')
# )
# jobType = models.CharField(max_length=30, choices=CARPENTRY_CHOICES, default='other')
def __str__(self):
return self.name
Django Models
Django Serializer
/api editor
I would probably go with a job_type model, which has a name and a 'subtype' field.
class JobType(models.Model):
SubTypeChoices = (...)
name = models.CharField()
subtype = models.CharField(choices=SubTypeChoices, ...)
class Job(models.Model):
....
job_type = models.ForeignKey(JobType, ...)
....
This way you can associate your 'subtypes' with one job_type. And if for some reason you can have several job_types for a Job, use a ManyToMany field.

Django import_export error in exporting with foreignkey

I am trying to import a data set using import_export. There in one column in the data set that is based on the foreignkey (by actual "item_sku" value, rather by its "id") from another model. However, it keeps giving me the following error:
"Line number: 1 - Model_Model01 matching query does not exist. "
How can I fix this? I have been referring to the following sources: source 01 and source 02, but the issue still persists.
Here are my codes:
Models.py
from django.db import models
class Model_Model01(models.Model):
item_sku = models.CharField(max_length = 2, null = False, blank = False)
def __unicode__(self):
return self.item_sku
class Model_Model02(models.Model):
item_sku = models.ForeignKey(Model_Model01, on_delete = models.CASCADE, null = True, blank = False)
def __unicode__(self):
return self.item_sku
admin.py
from import_export import fields
from import_export.admin import ImportExportModelAdmin
from import_export.widgets import ForeignKeyWidget
from .models import (Model_Model01, Model_Model02)
class Admin_Model02(ImportExportModelAdmin):
item_sku = fields.Field(
column_name = "item_sku",
attribute = "item_sku",
widget = ForeignKeyWidget(Model_Model01, "item_sku")
)
class Meta:
model = Model_Model02
admin.site.register(Model_Model02, Admin_Model02)
You need to make a resource object in your admin. It has an import_id_field parameter that defines what the primary key should be.
Here is the example from the documentation:
from import_export import resources
from import_export.admin import ImportExportModelAdmin
from .models import Book
class BookResource(resources.ModelResource):
class Meta:
model = Book
import_id_fields = ('isbn',)
fields = ('isbn', 'name', 'author', 'price',)
class BookAdmin(ImportExportModelAdmin):
resource_class = BookResource

How to separate the model into two applications

I have one application and one model.
I want to separate the model on two applications, so that the user was managed from a separate application.
Is the transfer of this model will do the trick? What I have to do?
class User(AbstractUser):
country = models.CharField(max_length=2, choices=COUNTRY, default=RUSSIA)
Here is my models.py - must be separate
RUSSIA = 'RUS'
USA = 'USA'
GERMANY = 'GER'
COUNTRY = (
(RUSSIA, "Russia"),
(USA, "USA"),
(GERMANY, "Germany"),
)
class User(AbstractUser):
country = models.CharField(max_length=2, choices=COUNTRY, default=RUSSIA)
class Country(models.Model):
country = models.CharField(max_length=3, choices=COUNTRY, default=RUSSIA)
name_of_team = models.CharField(max_length=255, blank=True, null=True)
def __unicode__(self):
return self.name_of_team
You can create two applications, one for Users and one for Countries. Then put the User model in the Users app and the Country model in the Countries app.
Then in a third app you can import both as you need them:
from countries.models import Country
from users.models import User
Put this part of the code in the settings.py file:
RUSSIA = 'RUS'
USA = 'USA'
GERMANY = 'GER'
COUNTRY = (
(RUSSIA, "Russia"),
(USA, "USA"),
(GERMANY, "Germany"),
)
If you do this then you can access the constants from both apps like this:
from django.conf import settings
settings.COUNTRY
You can create two apps, one for users and one for countries, then you just import country model into user model.
Besides if you want to keep a relationship between countries and user you should use a ForeignKey. Sorry if it does not match with your logic but I'm not sure how your models have to looks like, it is a bit estrange for me.
Something like this:
country/models.py
RUSSIA = 'RUS'
USA = 'USA'
GERMANY = 'GER'
COUNTRY = (
(RUSSIA, "Russia"),
(USA, "USA"),
(GERMANY, "Germany"),
)
class Country(models.Model):
# I don't know why country attr in Country class
country = models.CharField(max_length=3, choices=COUNTRY, default=RUSSIA)
name_of_team = models.CharField(max_length=255, blank=True, null=True)
def __unicode__(self):
return self.name_of_team
user/models.py
from country.models import Country
class User(AbstractUser):
# ForeignKey, here you make the relation with country model
country = models.ForeignKey(Country)

Categories