so I have this model set up with django and mongoengine.
class Product(Document):
product_id = IntField()
title = StringField(max_length=255)
sources = ListField(ReferenceField(Source, dbref = True))
class Source(Document):
source_id = IntField()
source_type = StringField(choices=settings.PARENT_TYPE_CHOICES, max_length=50)
name = StringField(max_length=255)
url = URLField(max_length=2000)
meta = {"allow_inheritance": True}
And in my scrapy pipeline I save the following data:
class SaveItemPipeline(object):
def process_item(self, item, spider):
product = item["product"]
product["sources"] = self.create_sources(product)
saved_product,created = Product.objects.get_or_create(**product)
return item
def create_sources(self,product):
temp_sources = []
for source in product["sources"]:
print source
if source["source_type"] == "user":
temp_source,created = UserSource.objects.get_or_create(**source)
elif source["source_type"] == "store":
temp_source,created = StoreSource.objects.get_or_create(**source)
elif source["source_type"] == "collection":
temp_source,created = CollectionSource.objects.get_or_create(**source)
temp_sources.append(temp_source.id)
return temp_sources
Howerver, when I run the scraper, on save it gives me this error:
raise ValidationError(message, errors=errors, field_name=field_name)
mongoengine.errors.ValidationError:
[ObjectId('55787a07516ddcf4d93cd4c6'),
ObjectId('55787b07516ddcf5aff06fa9'),
ObjectId('55787b07516ddcf5aff06faa')] is not a valid ObjectId
By the way the UserSource and StoreSource...all inherit from Source so they are just subclasses.However, am I doing anything wrong here, I don't understand why it is giving me that error when product gets created.
Thanks!
You can use this
class Source(Document):
source_id = IntField()
class Product(Document):
sources = ListField(ReferenceField(Source, dbref = True))
src, created = Source.objects.create(source_id=1)
pd, _ = Product.objects.create(sources=[src])
It works for me. I am using mongoengine 0.8.7, pymongo 2.8
Related
I am trying to create an api that gets it's response from a flask-sqlalchemy database. But anytime I make a get request on postman it returns the last added data to the database only and I am trying to get all the data.
Below is my database model
class Data(db.Model):
uuid = db.Column(db.String(60), name = "uuid", nullable = False, primary_key = True)
timestamp = db.Column(db.DateTime, nullable = False, default = datetime.utcnow, primary_key=True)
decibel = db.Column(db.Integer, nullable = False)
then my get all request
class Sensor(Resource):
def get(self):
datas = Data.query.all()
all = {}
for data in datas:
all = {"uuid":str(data.uuid), "timestamp":str(data.timestamp), "decibel":data.decibel}
return all
Then my post request although this works just fine
class SensorData(Resource):
#marshal_with(resource_fields)
def post(self):
args = sensor_post.parse_args()
sensor_new =Data(uuid = args['uuid'], decibel = args["decibel"])
if args['uuid'] != generate_UUID():
abort(405)
db.session.add(sensor_new)
db.session.commit()
return sensor_new, 201
api.add_resource(SensorData, "/sensor")
api.add_resource(Sensor, "/sensor/all")
Please I would appreciate any form of help on this
I'm trying to create a Schema using marshmallow_sqlalchemy. I want to create a list out of two entries of the Database, x_coordinate and y_coordinate, however, I'm not sure how to do that.
Here's the Schema
from marshmallow_sqlalchemy import SQLAlchemySchema, auto_field
class LocationSQLAlchemySchema(SQLAlchemySchema):
class Meta:
model = Location
load_instance = True
location_id = auto_field('id')
name = auto_field('name')
user_uid = auto_field('customer_id')
maps_url = auto_field('maps_url')
coordinates = fields.List(Meta.model.x_coordinate,Meta.model.y_coordinate) #This is what I don't know how to define.
Here's the Model I'm using for this Schema:
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.mysql import INTEGER
db = SQLAlchemy()
class Location(db.Model):
__tablename__ = 'cleaning_locations'
id = db.Column(db.String(128), primary_key=True, unique = True)
name = db.Column(db.String(45), nullable = False)
customer_id = db.Column(db.String(45),nullable = False)
maps_url = db.Column(db.String(2048),nullable = False)
x_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
y_coordinate = db.Column(db.Numeric(precision = 8, scale=5), nullable = False)
address = db.Column(db.String(255))
country = db.Column(db.String(45))
state = db.Column(db.String(45))
size = db.Column(INTEGER(unsigned=True), nullable = False )
rooms = db.Column(INTEGER(unsigned=True), nullable = False )
bathrooms = db.Column(INTEGER(unsigned=True), nullable = False )
kitchens = db.Column(INTEGER(unsigned=True), nullable = False )
How can I make the Schema to represent the coordinates as a list containing the x_coordinate and the y_coordinate?
(newbie extra question). Is it a bad practice to use diferent variable names in the db model and in the Schema?
Please try this (untested):
from marshmallow_sqlalchemy import field_for
[...]
coordinates = fields.Tuple(
(field_for(Location, "x_coordinate"), field_for(Location, "y_coordinate"))
)
Not sure it is the best idea here because then you can't just cram the data loaded from the schema into the object init. But nothing prevents you from having an API (schemas) that differs from the DB representation.
I'm trying to use bulk_create in order to add objects to related models. Here i'm fetching the csv file through post request which contains required fields. As of now I can add items to models which is unrelated using the csv file and bulk_create and it's working.
class BulkAPI(APIView):
def post(self, request):
paramFile = io.TextIOWrapper(request.FILES['requirementfile'].file)
dict1 = csv.DictReader(paramFile)
list_of_dict = list(dict1)
objs = [
ManpowerRequirement(
project=row['project'],
position=row['position'],
quantity=row['quantity'],
project_location=row['project_location'],
requested_date=row['requested_date'],
required_date=row['required_date'],
employment_type=row['employment_type'],
duration=row['duration'],
visa_type=row['visa_type'],
remarks=row['remarks'],
)
for row in list_of_dict
]
try:
msg = ManpowerRequirement.objects.bulk_create(objs)
returnmsg = {"status_code": 200}
print('imported successfully')
except Exception as e:
print('Error While Importing Data: ', e)
returnmsg = {"status_code": 500}
return JsonResponse(returnmsg)
My models are:
class ManpowerRequirement(models.Model):
project = models.CharField(max_length=60)
position = models.CharField(max_length=60)
quantity = models.IntegerField()
project_location = models.CharField(max_length=60)
requested_date = models.DateField()
required_date = models.DateField()
employment_type = models.CharField(max_length=60,choices = EMPLOYMENT_TYPE_CHOICES,
default = 'Permanent')
duration = models.CharField(max_length=60)
visa_type = models.CharField(max_length=60)
remarks = models.TextField(blank = True , null=True)
def __str__(self):
return self.project
class Meta:
verbose_name_plural = "Manpower_Requirement"
class Fulfillment(models.Model):
candidate_name = models.CharField(max_length=60)
manpower_requirement = models.ForeignKey(ManpowerRequirement, on_delete=models.CASCADE)
passport_number = models.CharField(blank = True, max_length=60)
subcontract_vendors = models.CharField(max_length=200,blank = True , null=True ,default='')
joined_date = models.DateField(blank = True, null = True, default = '')
remarks = models.TextField( blank = True,null = True)
def __str__(self):
return self.candidate_name
class Meta:
verbose_name_plural = "Fulfillment"
class FulfillmentStatus(models.Model):
fulfillment = models.ForeignKey(Fulfillment, on_delete=models.CASCADE)
status = models.CharField(max_length=60)
status_date = models.DateField()
remarks = models.TextField( blank = True, null = True )
def __str__(self):
return self.fulfillment.candidate_name
class Meta:
verbose_name_plural = "FulfillmentStatus"
I don't know how to do the same using bulk_create for Fulfillment and FulfillmentStatus models which are related to ManpowerRequirement. Csv file which I recieve in order to bulkcreate for Fulfillment consists of all the fields of ManpowerRequirement and all fields of Fulfillment and FulfillmentStatus excluding the foreign keys and id fields.
in the past I had the same problem; I solved in that way
Assuming that in a single CSV row you have data for all models I'd go for
create a mapping between the main model and the linked ones (you could use row index as key
use bulk_create() on the main model
iterate the dict and use bulk_create() for the linked modules
items = []
mrs = []
for row in list_of_dict:
mr = ManpowerRequirement(...)
mrs.append(mr)
f = ManpowerRequirement(...)
fs = FulfillmentStatus(...)
items.append((mr, f, fs))
# create all Manpower Requirements
ManpowerRequirements.objects.bulk_create(mrs)
a = []
for mr, f, fs in items:
f.manpower_requirement = mr
a.append(f)
# create all Fulfillments
Fulfillment.objects.bulk_create(a)
a = []
for mr, f, fs in items:
fs.fulfillment = f
a.append(fs)
# create all FulfillmentStatus
FulfillmentStatus.objects.bulk_create(a)
not sure if you can do some optimization in looping but it should solve the problem with just 3 queries
For related models we can do like this
class FulfillmentAPI(APIView):
def post(self, request):
paramFile = io.TextIOWrapper(request.FILES['fulfillmentfile'].file)
dict1 = csv.DictReader(paramFile)
list_of_dict = list(dict1)
objs = [
Fulfillment(
manpower_requirement=ManpowerRequirement.objects.get(project=row['project'], position=row['position'], quantity=row['quantity'], requested_date=row['requested_date'],),
remarks=row['remarks'],
candidate_name=row['candidate_name'],
passport_number=row['passport_number'],
joined_date=row['joined_date'],
subcontract_vendors=row['subcontract_vendors'],
)
for row in list_of_dict
]
try:
msg = Fulfillment.objects.bulk_create(objs)
returnmsg = {"status_code": 200}
print('imported successfully')
except Exception as e:
print('Error While Importing Data: ', e)
returnmsg = {"status_code": 500}
return JsonResponse(returnmsg)
This is my Model class
class SubJobs(models.Model):
id = models.AutoField(primary_key = True)
subjob_name = models.CharField(max_length=32,help_text="Enter subjob name")
subjobtype = models.ForeignKey(SubjobType)
jobstatus = models.ForeignKey(JobStatus, default= None, null=True)
rerun = models.ForeignKey(ReRun,help_text="Rerun")
transfer_method = models.ForeignKey(TransferMethod,help_text="Select transfer method")
priority = models.ForeignKey(Priority,help_text="Select priority")
suitefiles = models.ForeignKey(SuiteFiles,help_text="Suite file",default=None,null=True)
topofiles = models.ForeignKey(TopoFiles,help_text="Topo file",default=None,null=True)
load_image = models.NullBooleanField(default = True,help_text="Load image")
description = models.TextField(help_text="Enter description",null=True) command = models.TextField(help_text="Command",null=True)
run_id = models.IntegerField(help_text="run_id",null=True)
pid_of_run = models.IntegerField(help_text="pid_of_run",null=True)
hold_time = models.IntegerField()
created = models.DateTimeField(default=timezone.now,null=True)
updated = models.DateTimeField(default=timezone.now,null=True)
finished = models.DateTimeField(null=True)
The user might want to update a entry and may choose to update only few fields among these. How do I write a generic update statement that would update only the fields that were passed?
I tried this.
def update_subjob(request):
if (request.method == 'POST'):
subjobs_subjobid = request.POST[('subjob_id')]
post_data = request.POST
if 'subjob_name' in post_data:
subjobs_subjobname = request.POST[('subjob_name')]
if 'subjob_type' in post_data:
subjobs_subjobtype = request.POST[('subjob_type')]
if 'rerun_id' in post_data:
subjobs_rerun_id = request.POST[('rerun_id')]
if 'priority_id' in post_data:
subjobs_priority_id = request.POST[('priority_id')]
if 'transfer_method' in post_data:
subjobs_transfermethod = request.POST[('transfer_method')]
if 'suitefile' in post_data:
subjob_suitefile = request.POST[('suitefile')]
if 'topofile' in post_data:
subjob_topofile = request.POST[('topofile')]
try:
subjobinstance = SubJobs.objects.filter(id=subjobs_subjobid).update(subjob_name=subjobs_subjobname,
updated=datetime.now())
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)
How do I write a generic update to update only those fields which are sent in request.POST?
You'd better use Forms. But if you insist on your code it could be done like this.
Suppose you have variable field_to_update where every field that you are waiting in request is listed.
subjobs_subjobid = request.POST[('subjob_id')]
field_to_update = ('subjob_name','subjob_type', 'rerun_id', 'priority_id', 'transfer_method', 'suitefile', 'topofile')
post_data = request.POST
to_be_updated = {field: post_data.get(field) for field in field_to_update if field in post_data}
# then you need to get the object, not filter it
try:
subjobinstance = SubJobs.objects.get(id=subjobs_subjobid)
subjobinstance.update(**to_be_updated, updated=datetime.now())
except ObjectDoesNotExist: # from django.core.exceptions
print('There is no such object') # better to use logger
except Exception as e:
print("PROBLEM UPDAING SubJob!!!!")
print(e.message)
Hey folks i am getting integrity error while saving my views .Please tell me what i am doing wrong
Here is my django model
class Ruleinfo(models.Model):
rule = models.IntegerField(null=False)
From = models.IPAddressField(null=True)
to = models.IPAddressField(null=True)
priority = models.ForeignKey('Priority',related_name='pri_no')
cisp =models.ForeignKey('Priority',related_name = 'CISP_no')
def __unicode__(self):
return u'%s' %(self.rule)
class Priority(models.Model):
pri = models.IntegerField(null = True)
Ruleno = models.ForeignKey('Ruleinfo',related_name = 'ruleno_no')
CISP = models.IntegerField(null = True)
def __unicode__(self):
return u'%s ' % (self.priority)
My model form is looking like .
class RuleInfoForm(ModelForm):
class Meta:
model = Ruleinfo
fields = ("rule","From","to")
here is my views.py
def multiwanrule_info(request):
data = {}
no_of_isp = MultiWAN.objects.all()
try:
form = RuleInfoForm(request.POST)
except:
pass
print "----------------------------printing form"
print form
if form.is_valid():
rl_frm = form.save(commit=False)
get_priorities = request.POST.getlist('priority')
get_cisp_info = request.POST.getlist('cisp')
rule_object = Ruleinfo()
for get_pri,get_ci in zip(get_priorities,get_cisp_info,):
pri_object = Priority.objects.get_or_create(Ruleno = rule_object)
pri_object.pri = get_pri
pri_object.CISP = get_ci
rl_frm.save()
else:
form = RuleInfoForm()
data['form'] = form
data['number_of_isp'] = no_of_isp
return render_to_response('networking.html',data)
I am getting the above error along this
networking_priority.Ruleno_id may not be NULL
help me out so that i could get back on track .
rule_object = Ruleinfo()
This just instantiates a new model object. It is not saved or assigned values. Since it is not saved it does not have an id value.
assigning your rule_object values: rule, from, to, priority, and cisp values, should fix your problem.