csv import to manytomanyfield Django - python

I used below code to import csv file to django model containing manytomanyfield Release.metamodules
>>> from app.models import Metamodule,Release
>>> reldata = csv.reader(open('/root/Django-1.6.5/django/bin/dashboard/release.csv'),delimiter=',')
for row in reldata:
q = Release(number = row[0],
notes= row[1],
changes = row[2],
metamodules = Metamodule.objects.filter(name = row[3]))
try:
q.save()
except:
# if the're a problem anywhere, you wanna know about it
print "there was a problem with line"
Error:
Traceback (most recent call last):
File "<console>", line 5, in <module>
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 416, in __init__
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'metamodules' is an invalid keyword argument for this function
As the field is ManyToManyField i used objects.fileter to get multiple records. But it is returning error.Please help me to fix this issue
models.py:
class Metamodule(models.Model):
name = models.CharField(max_length=50)
version = models.IntegerField(default=0)
modulename = models.ForeignKey(Module)
createdate = models.DateField(auto_now=True, null=True)
createdby = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
class Release(models.Model):
number = models.IntegerField(default=0)
notes = models.CharField(max_length=50)
changes = models.CharField(max_length=50)
metamodules = models.ManyToManyField(Metamodule)
def __unicode__(self):
return unicode(self.number)

You can't create your Release object like that. You cannot create m2m relations from unsaved objects. See here
Try something like this :
for row in reldata:
q = Release(number=row[0], notes=row[1], changes=row[2])
# You have to save the object before adding the m2m relations
q.save()
metamodules = Metamodule.objects.filter(name=row[3])
for metamodule in metamodules:
q.metamodules.add(metamodule)
There is probably a better way to do the for loop but this is what you want to achieve.

Related

How can I fix "ValueError: "<Klant: None - aCustomer>" needs to have a value for field "klant" before this many-to-many relationship can be used."

Here are the imports:
from django.db import models
from datetime import datetime, timedelta
from django.contrib.auth.models import User
This is the first class I defined. It is the status of the action (Actie) and it has a status-id and a status-name with a max_length attribute of 5 (todo, doing, done)
class Status(models.Model):
id = models.IntegerField(primary_key=True)
status_naam = models.CharField(max_length=5, default='todo')
def __str__(self):
return str(self.id) + " - " + self.status_naam
This is the second class Klant which means customer. It has an id, a customer-name and users from the customer which is a ManyToManyField referring to users from the the User-table django gives me.
class Klant(models.Model):
id = models.IntegerField(primary_key=True)
klant_naam = models.CharField(max_length=100, default='-')
klant_gebruiker = models.ManyToManyField(User)
def __str__(self):
return str(self.id) + " - " + self.klant_naam
This is the class Actie (Action or the action the user determines) which has an id, an action-name, a action-status which refers to the table Status here above, an action-publish-date, an ending-date (the deadline) and a customer-id which refers to Klant.
class Actie(models.Model):
id = models.IntegerField(primary_key=True)
actie_naam = models.CharField(max_length=150, default='-')
actie_status = models.ForeignKey(Status, default=1)
actie_aanmaakdatum = models.DateTimeField(default=datetime.now())
actie_einddatum = models.DateTimeField(default=datetime.now() + timedelta(days=1))
actie_klant = models.ForeignKey(Klant, default=1)
def __str__(self):
return str(self.id) + " - " + self.actie_naam
This is what I'm doing in the shell:
(InteractiveConsole)
>>> from MyApp.models import User, Klant
>>> klant1 = Klant.objects.create(klant_naam='aCustomer')
>>> user1 = User.objects.get(username='peterdevries')
>>> klant1.klant_gebruiker.add(user1)
Traceback (most recent call last):
File "C:\shell.py", line 69, in handle
self.run_shell(shell=options['interface'])
File "C:\shell.py", line 61, in run_shell
raise ImportError
ImportError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\related_descriptors.py", line 468, in __get__
return self.related_manager_cls(instance)
File "C:\related_descriptors.py", line 751, in __init__
(instance, self.source_field_name))
ValueError: "<Klant: None - aCustomer>" needs to have a value for field "klant" before this many-to-many relationship can be used.
>>>
So my question now is what do I have to do to fix this ValueError?
Your models look like they were autogenerated via inspectdb. The problem is that all your primary keys are IntegerFields. This means that Django does not know that the database will give them a value automatically, so does not update the field on creation with that value - and therefore can't create the many-to-many relation, which requires inserting pks from both sides into the linking table.
You could change the fields to AutoField, but the simplest solution is just to delete those definitions altogether - Django will automatically set the primary key to an AutoField named id if another pk is not defined.

Django - Select related or join on two different base models

I have two base models SiteData and Showoroom Service that have model structure as per the below.
I need the SiteData info but I also would like to get link_type from the showroomservice model if there is a matching ID.
ive tried a few things thus far, none are getting what I need, what is the best way to achieve this?
Thanks
select related
>>> nd = ShowroomService.objects.select_related('site').all()
>>> nd
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 229, in __repr__
return '<%s %r>' % (self.__class__.__name__, data)
File "/usr/local/lib/python3.6/site-packages/django/db/models/base.py", line 590, in __repr__
u = six.text_type(self)
TypeError: __str__ returned non-string (type SiteData)
Combining :
>>> complete_data = site_data | monitoring_data
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py", line 310, in __or__
combined.query.combine(other.query, sql.OR)
File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py", line 529, in combine
"Cannot combine queries on two different base models."
AssertionError: Cannot combine queries on two different base models.
chaining
>>> final_data = chain(monitoring_data, site_data)
>>> for i in final_data:
... '{} {}'.format(i.location,i.link_Type)
...
Traceback (most recent call last):
File "<console>", line 2, in <module>
AttributeError: 'ShowroomService' object has no attribute 'location'
sites.models.py
class SiteData(models.Model):
location = models.CharField(max_length=50)
site_type = models.ForeignKey(SiteTypes, verbose_name="Site Type", \
on_delete=models.PROTECT)
subnet = models.GenericIPAddressField(protocol='IPv4')
routed_subnet = models.GenericIPAddressField(protocol='IPv4', \
verbose_name="Routed Link Subnet", blank=True, null=True)
bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
opening_date = models.DateField(verbose_name="Showroom opening date")
last_hw_refresh_date = models.DateField(verbose_name="Date of latest hardware refresh", \
blank=True, null=True)
is_live = models.BooleanField(default=False, verbose_name="Is this a live site?")
tel = models.CharField(max_length=20, blank=True, null=True)
address = models.CharField(max_length=255, blank=True, null=True)
town = models.CharField(max_length=255, blank=True, null=True)
...
class Meta:
verbose_name = "Site Data"
verbose_name_plural = "Site Data"
ordering = ('location',)
permissions = (
("can_view", "Can View"),
("can_view_mgmt", "Can View Management"),
)
def __str__(self):
return self.location
monitoring.models.py
from sites.models import SiteData
class ShowroomService(models.Model):
site = models.ForeignKey(SiteData, verbose_name="Site", \
on_delete=models.PROTECT)
link_type = models.CharField(max_length=200, blank=True, null=True)
preference = models.CharField(max_length=200, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True, blank=True, null=True)
dashboard = models.BooleanField(default=True, verbose_name="display on monitoring dashboard?")
class Meta:
verbose_name = "Showroom Service Data"
verbose_name_plural = "Showroom Service Data"
def __str__(self):
return self.site
You can pull all related objects using django's "related manager". Documentation is available here: https://docs.djangoproject.com/en/2.0/ref/models/relations/#related-objects-reference
By calling showroom_service_set on a SiteData model, you can get the set of child records for each SiteData.
Just to explain why the listed attempts failed as well:
your __str__ methods on your models need to return strings. If they don't, you'll get that exception.
The pipe operator | is used for ORing together queries in django. That chunk of code is attempting to combine a query for 2 different types of models.
With the chain attempt, you've created a list containing two different types of models. One of which doesn't have a location attribute.
Here's a chunk of code to get the link type for all ShowroomService models attached to a SiteData model:
for site_data in SiteData.objects.all():
for showroom in site_data.showroom_service_set.all():
print showroom.link_type
I'm not sure how django handles camel-casing with related objects, so showroom_service_set is my best guess. You might have to do a little leg work on this to figure out what the actual set is called.
EDIT: There's something called prefetch_related. Here's a SO answer about it; I think it'll get you what you're looking for: https://stackoverflow.com/a/13096423/769971

Django getting "first_name" is invalid keyword argument for this function" TypeError when creating an instance of my model class

Using Django 1.11 and django-pyodbc-azure latest version if it is relevant.
I am new to Django and have been following along the 1.11 tutorial without any issues until this, and I am incredibly confused.
Here is my models.py:
from django.db import models
# Create your models here.
class Player(models.Model):
first_name = models.CharField(max_length=20, name='First Name')
last_name = models.CharField(max_length=20, name='Last Name')
def __str__(self):
return '{}, {} ({})'.format(self.last_name, self.first_name, self.id)
class Game(models.Model):
players = models.ManyToManyField(Player, name='Players')
def __str__(self):
return ' vs. '.join(self.players)
class Round(models.Model):
GIN = 'GI'
UNDERCUT = 'UN'
KNOCK = 'KN'
ENDING_ACITONS = (
(GIN, 'Gin'),
(UNDERCUT, 'Undercut'),
(KNOCK, 'Knock'),
)
game = models.ForeignKey(Game, on_delete=models.CASCADE, name='Parent Game')
winner = models.ForeignKey(Player, on_delete=models.CASCADE, name='Winning Player')
points = models.IntegerField(name='Points Awarded')
end = models.CharField(max_length=2, choices=ENDING_ACITONS)
def __str__(self):
return '{} awarded {} points via {}'.format(self.winner, self.points, self.end.name)
Now when I run manage.py shell and type:
from game.models import *
bobby = Player(first_name='Bobby', last_name='Fisher')
I am met with this error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Users\mteper\PycharmProjects\GinRummy\venv\lib\site-packages\django\db\models\base.py", line 571, in __init__
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'first_name' is an invalid keyword argument for this function
Any insight would be greatly appreciated, as, like I said earlier, I am new to Django and Python in general.
It is the name argument that is causing problems. You should set verbose_name instead.
class Player(models.Model):
first_name = models.CharField(max_length=20, verbose_name='First Name')
last_name = models.CharField(max_length=20, verbose_name='Last Name')

'tuple' object has no attribute - Django

I'm trying to save some data to my database, but I keep getting the error: 'tuple' object has no attribute 'view_id I think that somehow I'm getting the object wrongly from my db.
Models.py
class GoogleProperty(models.Model): # Settings for each single site, a user can have many!
user = models.CharField(max_length=200) # Owner of site
google_email = models.EmailField(max_length=200)
profile_id = models.CharField(max_length=200) # Needed to delete users, but should be removed!
property_name = models.CharField(max_length=200, blank=True, null=True)
property_id = models.CharField(max_length=200, blank=True, null=True)
property_url = models.CharField(max_length=200, blank=True, null=True)
view_id = models.CharField(max_length=200)
def __str__(self):
return str(self.property_url)
Views.py
def some_function(requests):
if len(list_of_views)==1: # Save to DB and call it a day
view_name = list_of_views[0]['name']
view_id = list_of_views[0]['id']
print(view_id) # 123823290
dic_views[view_name]=view_id
# Save View to DB
'''
obj, created = GoogleProperty.objects.get_or_create(google_email=current_user, defaults={'view_id': view_id})
if not created:
obj.view_id = view_id
obj.save()
'''
objx = GoogleProperty.objects.get_or_create(google_email=current_user)
print(objx) # (<GoogleProperty: None>, False)
objx.view_id = view_id
objx.save
return HttpResponse(request, '/ga_app/report.html', {'view_id':view_id})
else: # Many Views, ask which one they want to track
Do something
edit added traceback:
File "/my-path/views.py", line 212, in select_view
objx.view_id = view_id
AttributeError: 'tuple' object has no attribute 'view_id'
I've put as side note the results of the print() function.
Also, in some parts of my code I add the defaults={'view_id': view_id} is that really needed? If so why?
P.s. I tried both codes that commented out and the one not commented out.
You had the correct approach commented out, why?
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#get-or-create get_or_create returns a tuple of the form (object, created [boolean]).
What you'd want to do is split out the result of that command:
objx, created = GoogleProperty.objects.get_or_create(google_email=current_user)
Then you can do:
if not created:
objx.view_id = view_id
objx.save()
You seem to have syntax errors. objx is a tuple, tuples are indexed by integers, and also tuples are immutable in python, so this should work.
objx[0].view_id = view_id
objx[0].save()
and defaults are provided to set default attributes incase of object creation. So basically you are setting a default view_id, if the object is created.
Provide the stack trace for the commented out part also.
#Costantin : You are calling to a property of tuple object that no exist so that is why you have getting error ex:
>>> t = ('23','e')
>>> t[1]
'e'
>>> t.r
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'r'

Saving files to upload field in Django using a Python script

Building an application to list reports for inspections. The actual inspection report is going to be made available for download. Saving the reports to the database using django-db-file-storage.
Lots of records to process, so writing a script to do everything in bulk. Testing in the manage.py shell throws an error.
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from inspections.models import InspectionInformation, RestaurantInformation
file = open('/docs/Data/2011/12/12-07-11_1498.pdf', 'r').read()
InspectionInformation(
insp_rest_permit=RestaurantInformation.objects.get(rest_permit=int('1814')),
insp_date='2011-12-12',
insp_score='100',
insp_inspector='Philip',
insp_report=default_storage.save('report.pdf', ContentFile(file))
).save()
Traceback
Traceback (most recent call last):
File "<console>", line 6, in <module>
File "/venv/lib/python2.7/site-packages/django/core/files/storage.py", line 48, in save
name = self.get_available_name(name)
File "/venv/lib/python2.7/site-packages/django/core/files/storage.py", line 74, in get_available_name
while self.exists(name):
File "/venv/lib/python2.7/site-packages/db_file_storage/storage.py", line 77, in exists
model_class_path, content_field, filename_field, mimetype_field, filename = name.split('/')
ValueError: need more than 1 value to unpack
Models
from django.db import models
class RestaurantInformation(models.Model):
rest_permit = models.IntegerField(unique=True, verbose_name='Permit')
rest_name = models.CharField(max_length=200, verbose_name='Name')
rest_address = models.CharField(max_length=200, verbose_name='Address')
rest_city = models.CharField(max_length=100, verbose_name='City')
rest_zip = models.IntegerField(verbose_name='Zip Code')
rest_owner = models.CharField(max_length=200, verbose_name='Owner')
rest_latitude = models.CharField(max_length=40, verbose_name='Latitude')
rest_longitude = models.CharField(max_length=40, verbose_name='Longitude')
class Meta:
ordering = ['rest_name']
def __unicode__(self):
return self.rest_name + ', ' + self.rest_address + ', ' + self.rest_city
class InspectionInformation(models.Model):
insp_rest_permit = models.ForeignKey(RestaurantInformation, null=False, to_field='rest_permit')
insp_score = models.DecimalField(verbose_name='Score', decimal_places=2, max_digits=5)
insp_date = models.DateField(verbose_name='Date')
insp_inspector = models.CharField(max_length=200, verbose_name='Inspector')
insp_report = models.FileField(upload_to='restaurants.InspectionFile/bytes/filename/mimetype',
blank=True, null=True, verbose_name='Inspection Report')
class Meta:
unique_together = ("insp_rest_permit", "insp_score", "insp_date")
ordering = ['insp_date']
class InspectionFile(models.Model):
bytes = models.TextField()
filename = models.CharField(max_length=255)
mimetype = models.CharField(max_length=50)
1.It looks like db_file_storage.storage.save() expects their custom format specified to be used with the model plus the filename e.g. "console.ConsolePicture/bytes/filename/mimetype" + filename.
So for your example instead of
'report.pdf'
it would be
'restaurants.InspectionFile/bytes/filename/mimetype/report.pdf'
I looked at the documentation and it isn't clear why it's being done this way as this violates DRY by making you enter the same thing twice, but they use the same format throughout the DatabaseFileStorage class.
2.It also looks like there's a bug in the save method (line 60) where
mimetype = content.file.content_type
should be changed to
mimetype = content.content_type
And the file you pass it should be something with a content_type attribute so probably a Django SimpleUploadedFile:
from django.core.files.uploadedfile import SimpleUploadedFile
file_ = SimpleUploadedFile('report.pdf', open('/docs/Data/2011/12/12-07-11_1498.pdf', 'r').read())
The reason I think this is a bug is that when I tried passing in a mock object that looked like "content.file.content_type" I got a Python core library exception later on.

Categories