def reset_password(request): args = {} args.update(csrf(request)) if request.method == 'POST': form = PasswordResetForm(request.POST) args['form'] = form if form.is_valid(): try: save_point = transaction.savepoint() password_reset_token = generate_activation_key(form.cleaned_data['email']) user = User.objects.get(email=form.cleaned_data['email']) user.userprofile.password_token = password_reset_token user.userprofile.save() email_subject = 'Password reset confirmation' email_body = "Hi %s, to reset the password, click this link http://127.0.0.1:8000/reset_password_confirm/%s" % (user.username, password_reset_token) send_mail(email_subject, email_body, settings.EMAIL_HOST_USER, [user.email], fail_silently=False) except: transaction.savepoint_rollback(save_point) err_message = (sys.exc_info()[1]) messages.add_message(request,messages.ERROR,err_message) else: transaction.savepoint_commit(save_point) messages.add_message(request,messages.SUCCESS,'The Password reset confirmation link has been sent to your email') args['form'] = PasswordResetForm() else: args['form'] = PasswordResetForm() return render_to_response('reset_password.html', args, context_instance=RequestContext(request))
def FetchOrCreate(cls,s): """ Find an entry for this set of intolerances, check the cache first. Otherwise check the database, if necessary creating a new item. """ if s in cls.__cache: return cls.__cache[s]; while True: created =False try: sid = transaction.savepoint() e, created = cls.objects.get_or_create(intolerant_for_extension = s) transaction.savepoint_commit(sid) except DatabaseError: transaction.savepoint_rollback(sid) time.sleep(0.1) continue except IntegrityError: transaction.savepoint_rollback(sid) time.sleep(0.1) continue break; if not created: cls.__cache[s]=e return e;
def FetchOrCreateItem(cls,**params): """ Either find an existing entry matching the config & results in the params dictionary, or create a new entry. """ key = cls._CalculateKey(**params) if key in cls.__cache: return cls.__cache[key]; params1 = dict(params) params1.pop("servername",None) params1.pop("part_of_run", None) while True: created =False try: sid = transaction.savepoint() item,created = ProbeCommonResultEntry.objects.get_or_create(key=key, defaults=params1) transaction.savepoint_commit(sid) except DatabaseError: transaction.savepoint_rollback(sid) time.sleep(0.1) continue except IntegrityError: transaction.savepoint_rollback(sid) time.sleep(0.1) continue break; if not created: cls.__cache[key] = item return item
def reset_password_confirm(request,password_reset_token): args = {} args.update(csrf(request)) args['link_expired'] = False args['password_reset_token'] = password_reset_token try: user_profile = get_object_or_404(UserProfile,password_token=password_reset_token) if request.method == 'POST': form = PasswordResetConfirmForm(request.POST) args['form'] = form if form.is_valid(): try: save_point = transaction.savepoint() if user_profile.user.check_password(form.cleaned_data['password2']): raise forms.ValidationError('New password should not be the same as old password') user_profile.user.set_password(form.cleaned_data['password2']) user_profile.user.save() user_profile.password_token=None user_profile.save() except forms.ValidationError as e: transaction.savepoint_rollback(save_point) messages.add_message(request,messages.ERROR,e.message) except: transaction.savepoint_rollback(save_point) err_message = (sys.exc_info()[1]) messages.add_message(request,messages.ERROR,err_message) else: transaction.savepoint_commit(save_point) messages.add_message(request,messages.SUCCESS,'Password has been successfully changed and the link has been expired') args['link_expired'] = True else: args['form'] = PasswordResetConfirmForm() except Http404 as e: args['link_expired'] = True return render_to_response('reset_password_confirm.html', args, context_instance=RequestContext(request))
def GetIPLock(cls,run, ip_address, server_item): """ Obtain a lock for this particular IP address in this run If an entry already exists, report that back, along with the entry """ while True: try: ip = IP_Address.objects.extra(where=['"probedata2_ip_address"."ip_address" = INET(E\''+ip_address+'\')'])[0] except (IP_Address.DoesNotExist, IndexError): try: sid = transaction.savepoint() ip = IP_Address.objects.create(ip_address=ip_address); ip.Construct() sid = transaction.savepoint_commit(sid) except: sid = transaction.savepoint_rollback(sid) continue break; while True: try: sid = transaction.savepoint() (probedalready,created) = cls.objects.get_or_create( part_of_run=run, ip_address=ip, port = server_item.port, protocol =server_item.protocol, defaults={"server":server_item}) sid = transaction.savepoint_commit(sid) except: sid = transaction.savepoint_rollback(sid) time.sleep(0.1) continue; break; return (probedalready,created)
def save(self, actor, organization, ip_address): om = super(InviteOrganizationMemberForm, self).save(commit=False) om.organization = organization om.type = OrganizationMemberType.MEMBER try: existing = OrganizationMember.objects.filter(organization=organization, user__email__iexact=om.email)[0] except IndexError: pass else: return existing, False sid = transaction.savepoint(using="default") try: om.save() except IntegrityError: transaction.savepoint_rollback(sid, using="default") return OrganizationMember.objects.get(email__iexact=om.email, organization=organization), False transaction.savepoint_commit(sid, using="default") AuditLogEntry.objects.create( organization=organization, actor=actor, ip_address=ip_address, target_object=om.id, event=AuditLogEntryEvent.MEMBER_INVITE, data=om.get_audit_log_data(), ) om.send_invite_email() return om, True
def get_or_create(self, **kwargs): """ Looks up an object with the given kwargs, creating one if necessary. Returns a tuple of (object, created), where created is a boolean specifying whether an object was created. """ assert kwargs, \ 'get_or_create() must be passed at least one keyword argument' defaults = kwargs.pop('defaults', {}) try: return self.get(**kwargs), False except self.model.DoesNotExist: try: params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) params.update(defaults) obj = self.model(**params) sid = transaction.savepoint() obj.save(force_insert=True) transaction.savepoint_commit(sid) return obj, True except IntegrityError, e: transaction.savepoint_rollback(sid) try: return self.get(**kwargs), False except self.model.DoesNotExist: raise e
def save(self, *args, **kwargs): if not self.pk and not self.slug: self.slug = self.slugify(self.name) if django.VERSION >= (1, 2): from django.db import router using = kwargs.get("using") or router.db_for_write(type(self), instance=self) # Make sure we write to the same db for all attempted writes, # with a multi-master setup, theoretically we could try to # write and rollback on different DBs kwargs["using"] = using trans_kwargs = {"using": using} else: trans_kwargs = {} i = 0 while True: i += 1 try: sid = transaction.savepoint(**trans_kwargs) res = super(TagBase, self).save(*args, **kwargs) transaction.savepoint_commit(sid, **trans_kwargs) return res except IntegrityError: transaction.savepoint_rollback(sid, **trans_kwargs) self.slug = self.slugify(self.name, i) else: return super(TagBase, self).save(*args, **kwargs)
def bulk_insert(cursor, rpm_nevra, filename, srpm_nevra=None): nvra = parse_nvra(rpm_nevra) if srpm_nevra: srpm_name = parse_nvra(srpm_nevra)["name"] else: srpm_name = nvra["name"] sql = add_returning("""INSERT INTO %s (name, epoch, version, release, arch, srpm_nevra, srpm_name, filename) VALUES (%%s, %%s, %%s, %%s, %%s, %%s, %%s, %%s)""" % RPM._meta.db_table) try: sid = transaction.savepoint() RPM.check_srpm_nevra(rpm_nevra, srpm_nevra) cursor.execute(sql, [nvra["name"], nvra["epoch"], nvra["version"], nvra["release"], nvra["arch"], srpm_nevra, srpm_name, filename]) if connection.features.can_return_id_from_insert: insert_id = connection.ops.fetch_returned_insert_id(cursor) else: insert_id = connection.ops.last_insert_id(cursor, RPM._meta.db_table, "id") except (IntegrityError, ValidationError): transaction.savepoint_rollback(sid) cursor.execute("""SELECT %s FROM %s WHERE name=%%s AND epoch=%%s AND version=%%s and release=%%s AND arch=%%s""" % ("id", RPM._meta.db_table), [nvra["name"], nvra["epoch"], nvra["version"], nvra["release"], nvra["arch"]]) insert_id = int(cursor.fetchone()[0]) transaction.savepoint_commit(sid) return insert_id
def accept_results(request): """accept data submissions from the lab via POST. see connection() in extract.py for how to submit; attempts to save raw data/partial data if for some reason the full content is not parseable or does not validate to the model schema""" if request.META['CONTENT_TYPE'] != 'text/json': logger.warn('incoming post does not have text/json content type') content = request.raw_post_data payload_date = datetime.now() payload_user = request.user try: data = json.loads(content) except: data = None #safety -- no matter what else happens, we'll have the original data payload = labresults.Payload.objects.create(incoming_date=payload_date, auth_user=payload_user, parsed_json=data is not None, raw=content) sid = transaction.savepoint() if not data: #if payload does not parse as valid json, save raw content and return error return HttpResponse('CANNOT PARSE (%d bytes received)' % len(content)) try: process_payload(payload, data) except: logging.exception('second stage result parsing failed; rolling back ' 'to savepoint.') transaction.savepoint_rollback(sid) return HttpResponse('SUCCESS')
def __exit__(self, exc_type, exc_value, traceback): if exc_value is None: # commit operation if self.sid is None: # Outer transaction try: transaction.commit(self.using) except: transaction.rollback(self.using) raise finally: self._leave_transaction_management() else: # Inner savepoint try: transaction.savepoint_commit(self.sid, self.using) except: transaction.savepoint_rollback(self.sid, self.using) raise else: # rollback operation if self.sid is None: # Outer transaction transaction.rollback(self.using) self._leave_transaction_management() else: # Inner savepoint transaction.savepoint_rollback(self.sid, self.using) return False
def get_or_create(self, **kwargs): """ This is a copy of QuerySet.get_or_create, that forces calling our custom create method when the get fails. """ assert kwargs, \ 'get_or_create() must be passed at least one keyword argument' defaults = kwargs.pop('defaults', {}) try: self._for_write = True return self.get(**kwargs), False except self.actual_model.DoesNotExist: params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) params.update(defaults) obj = self.model(**params) self._for_write = True self._instance = obj using = self.db try: sid = transaction.savepoint(using=using) obj.save(force_insert=True, using=using) except IntegrityError, e: transaction.savepoint_rollback(sid, using=using) try: return self.get(**kwargs), False except self.actual_model.DoesNotExist, e: raise self.actual_model.DoesNotExist(unicode(e).replace(self.model.__name__, self.actual_model.__name__))
def forwards(self, orm): # Changing field 'Tale.slug' db.alter_column('tales_tale', 'slug', self.gf('django.db.models.fields.SlugField')(max_length=100, unique=True, null=True, db_index=False)) if not db.dry_run: orm.Tale.objects.all().update(slug=None) # Adding unique constraint on 'Tale', fields ['slug'] db.create_unique('tales_tale', ['slug']) if not db.dry_run: for tale in orm.Tale.objects.order_by('pk'): tale.slug = slugify(tale.title) i = 0 while True: i += 1 try: sid = transaction.savepoint() tale.save() transaction.savepoint_commit(sid) break except IntegrityError: transaction.savepoint_rollback(sid) tale.slug = slugify(tale.title, i) # Removing null=True. We need it only for update. db.alter_column('tales_tale', 'slug', self.gf('django.db.models.fields.SlugField')(max_length=100, unique=True, null=False, db_index=False))
def save_manager_information(request): sid = transaction.savepoint() try: if request.method == "POST": rm_obj = RelationShipManager( rm_first_name = request.POST.get('first_name'), rm_last_name = request.POST.get('last_name'), rm_email = request.POST.get('manager_email'), rm_contactno = request.POST.get('manager_number'), rm_status = 1, rm_creation_date=datetime.datetime.now() ) rm_obj.save() print "done" rm_obj.rm_unique_id=str('RM'+ datetime.date.today().strftime('%d%m%y') + str(rm_obj.relationship_manager_id).zfill(4)) rm_obj.save() transaction.savepoint_commit(sid) data = {'success': 'true', 'manager_id':rm_obj.relationship_manager_id, 'manager_name':rm_obj.rm_first_name +" "+ rm_obj.rm_last_name } else: print 'Invalid Request' data = {'sucess': 'false' , ExceptionLabel.ERROR_MESSAGE :'Invalid Request'} except Exception, e: transaction.savepoint_rollback(sid) print 'error',e data = {'sucess': 'false', ExceptionLabel.ERROR_MESSAGE :'Server Error'}
def test_prevent_rollback(self): with transaction.atomic(): Reporter.objects.create(first_name="Tintin") sid = transaction.savepoint() # trigger a database error inside an inner atomic without savepoint with self.assertRaises(DatabaseError): with transaction.atomic(savepoint=False): connection.cursor().execute( "SELECT no_such_col FROM transactions_reporter" ) # prevent atomic from rolling back since we're recovering manually self.assertTrue(transaction.get_rollback()) transaction.set_rollback(False) transaction.savepoint_rollback(sid) self.assertQuerysetEqual(Reporter.objects.all(), ['<Reporter: Tintin>']) self.assertAtomicSignalCalls( # Enter atomic transaction block. enter_block_atomic_signal_call_sequence(True) + # Create Reporter. create_model_atomic_signal_call_sequence() + # Enter and leave atomic transaction block. enter_block_atomic_signal_call_sequence(False, savepoint=False) + leave_block_atomic_signal_call_sequence(False, False, savepoint=False) + # Leave atomic transaction with recovered rollback. leave_block_atomic_signal_call_sequence(True, True) )
def create(row, model, model_attrs, related_attrs, processor): sid = transaction.savepoint() try: with transaction.atomic(): _create_instances(model, model_attrs, related_attrs) except (Error, ValueError, AttributeError, TypeError, IndexError): transaction.savepoint_rollback(sid) error_message = traceback.format_exc() if 'File' in error_message: error_message = 'File{}'.format( error_message.split('File')[-1]) value = { 'model_attrs': model_attrs, 'related_attrs': related_attrs } error_raised.send(processor, error=error_message, position=row, value=value, step=ErrorChoicesMixin.IMPORT_DATA)
def save_company_information(request): # pdb.set_trace() sid = transaction.savepoint() try: if request.method == "POST": company_obj = Company( company_name = request.POST.get('company_name'), company_email = request.POST.get('company_email'), company_phone_no = request.POST.get('contact_number'), company_address = request.POST.get('address_line'), company_city = request.POST.get('city'), company_state = request.POST.get('state'), company_country = request.POST.get('country'), company_pincode = request.POST.get('pincode'), company_creation_date=datetime.datetime.now() ) company_obj.save() print "done" company_obj.company_unique_id=str('CO'+ datetime.date.today().strftime('%d%m%y') + str(company_obj.company_id).zfill(4)) company_obj.save() transaction.savepoint_commit(sid) data = {'success': 'true', 'company_id':company_obj.company_id, 'company_name':company_obj.company_name } else: print 'Invalid Request' transaction.savepoint_rollback(sid) data = {'sucess': 'false' , ExceptionLabel.ERROR_MESSAGE :'Invalid Request'} except Exception, e: transaction.savepoint_rollback(sid) print 'error',e data = {'sucess': 'false', ExceptionLabel.ERROR_MESSAGE :'Server Error'}
def migrate_app(sender, *args, **kwargs): """ Migrate all models of this app registered """ from .registration import registry if 'app_config' not in kwargs: return app_config = kwargs['app_config'] app_name = app_config.label fields = [fld for fld in registry._field_registry.keys() if fld.startswith(app_name)] sid = transaction.savepoint() for fld in fields: model_name, field_name = fld.split('.')[1:] if field_exists(app_name, model_name, field_name): continue model = app_config.get_model(model_name) try: with connection.schema_editor() as schema_editor: schema_editor.add_field(model, registry._field_registry[fld]) transaction.savepoint_commit(sid) except ProgrammingError: transaction.savepoint_rollback(sid) continue
def testmail(request): try: kwargs = dict(instance=models.Email.objects.order_by("-id")[0]) except IndexError: kwargs = {} form = forms.EmailForm(request.POST, **kwargs) if not form.is_valid(): return JsonResp(request, form=form) email = bsdUsers.objects.get(bsdusr_username="******").bsdusr_email if not email: return JsonResp(request, error=True, message=_("You must configure the root email" " (Accounts->Users->root)")) sid = transaction.savepoint() form.save() error = False if request.is_ajax(): sw_name = get_sw_name() error, errmsg = send_mail( subject=_("Test message from %s" % (sw_name)), text=_("This is a message test from %s" % (sw_name,)) ) if error: errmsg = _("Your test email could not be sent: %s") % errmsg else: errmsg = _("Your test email has been sent!") transaction.savepoint_rollback(sid) return JsonResp(request, error=error, message=errmsg)
def delete(self, request, *args, **kwargs): sid = transaction.savepoint() try: association = Association.objects.get( id=UserToken.get_association_id(request.session)) if Enterprise.objects.filter(headquar__association_id=UserToken.get_association_id(request.session)).count() == 1: raise Exception( (u"Asociación <b>%(name)s</b> no puede quedar sin ninguna sede asociada.") % {"name": association.name}) d = self.get_object() # rastrear dependencias deps, msg = get_dep_objects(d) if deps: messages.warning(self.request, _('Cannot delete %(name)s') % { "name": capfirst(force_text(self.model._meta.verbose_name)) + ' "' + force_text(d) + '"' }) raise Exception(msg) d.delete() msg = _('The %(name)s "%(obj)s" was deleted successfully.') % { 'name': capfirst(force_text(self.model._meta.verbose_name)), 'obj': force_text(d) } if not d.id: messages.success(self.request, msg) log.warning(msg, extra=log_params(self.request)) except Exception, e: try: transaction.savepoint_rollback(sid) except: pass messages.error(request, e) log.warning(force_text(e), extra=log_params(self.request))
def form_valid(self, form): sid = transaction.savepoint() try: self.object = form.save(commit=True) headquar = Headquar() headquar.name = self.request.POST.get("sede") headquar.association_id = UserToken.get_association_id( self.request.session) headquar.enterprise = self.object headquar.save() msg = _('The %(name)s "%(obj)s" was added successfully.') % { 'name': capfirst(force_text(self.model._meta.verbose_name)), 'obj': force_text(self.object) } if self.object.id: messages.success(self.request, msg) log.warning(msg, extra=log_params(self.request)) return super(EnterpriseCreateView, self).form_valid(form) except Exception, e: try: transaction.savepoint_rollback(sid) except: pass messages.success(self.request, e) log.warning(force_text(e), extra=log_params(self.request)) return super(EnterpriseCreateView, self).form_invalid(form)
def unregisterAgentForServiceToday(self,ani,connection=0,date=None): """ """ log.info("in unregisterAgentForServiceToday for agent.ani: " + ani) assert(ani) today = date or datetime.date.today() sid = None try: #verify agent is active if (self.isANICurrentlyActive(ani)): log.info("in unregisterAgentForServiceToday. Agent exists and currently active. About to set as inactive") log.info(today.__str__()) #unregister agent agent = Agents.objects.filter(ani=ani, connection_status=1).extra(where=["added between %s and %s"], params=["%s 00:00:00" % (today.__str__()), "%s 24:00:00" % (today.__str__())])[0] #set agent as off log.info(agent) agent.connection_status=0 log.info("agent connection status:%s ani: %s " % (agent.connection_status,agent.ani)) assert(agent.connection_status == connection) log.info("in unregisterAgentForServiceToday about to save agent") agent.save() log.info("in unregisterAgentForServiceToday agent saved") sid = transaction.savepoint() transaction.savepoint_commit(sid) return agent else: #agent was not registered for service return None except Exception as e: log.info("services.gateway.unregisterAgentForServiceToday: " + e) transaction.savepoint_rollback(sid) return None
def save(self, force_insert=False, force_update=False, using=None): sid = transaction.savepoint() if self.pk is None: i = 1 while self.pk is None: if i > 10: sleep(0.001) if i > 20: # Protection from infinite loop raise IntegrityError("Too many iterations while generating " "unique Invoice number.") try: self.created_on = datetime.utcnow() self.created_on = self.created_on - timedelta(microseconds=self.created_on.microsecond % 100) self.payment_no = ( self.created_on.hour * 3600 + self.created_on.minute * 60 + self.created_on.second ) * 10000 + (self.created_on.microsecond // 100) super(Invoice, self).save(force_insert, force_update) except IntegrityError: transaction.savepoint_rollback(sid) i += 1 else: super(Invoice, self).save(force_insert, force_update) transaction.savepoint_commit(sid) transaction.commit()
def forwards(self, orm): # Adding model 'ProjectDomain' db.create_table('sentry_projectdomain', ( ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='domain_set', to=orm['sentry.Project'])), ('domain', self.gf('django.db.models.fields.CharField')(max_length=128)), )) db.send_create_signal('sentry', ['ProjectDomain']) # Adding unique constraint on 'ProjectDomain', fields ['project', 'domain'] db.create_unique('sentry_projectdomain', ['project_id', 'domain']) sid = transaction.savepoint() try: # Adding index on 'Message', fields ['checksum'] db.create_index('sentry_message', ['checksum']) except: transaction.savepoint_rollback(sid) sid = transaction.savepoint() try: # Adding index on 'Message', fields ['checksum'] db.create_index('sentry_groupedmessage', ['checksum']) except: transaction.savepoint_rollback(sid)
def test_construction(self): # Should be able to construct normally, UI or Admin try: ma = self.createMachineApp(TEST_ADMINAPPS, 1) except: self.fail('Unable to construct AdminApp with standard args') else: self.assertEqual(ma, MachineApp.objects.get(pk=ma.pk)) try: ma2 = self.createMachineApp(TEST_UIAPPS, 1) except: self.fail('Unable to construct UIApp with standard args') else: sid = transaction.savepoint() self.assertEqual(ma2, MachineApp.objects.get(pk=ma2.pk)) # Should not be able to construct two apps with same email try: ma3 = self.createMachineApp(TEST_ADMINAPPS, 1, force_create=True) except: transaction.savepoint_rollback(sid) else: self.fail('Constructed two AdminApps with the same email') # Even if they are different app types try: overrides = {'app_type':'chrome'} ma4 = self.createMachineApp(TEST_ADMINAPPS, 1, force_create=True, **overrides) except: transaction.rollback() else: self.fail('Constructed an AdminApp and a ChromeApp with the same email')
def restore_models(zip_config, models_to_restore): """ Add models in tuple of tuples models_to_restore to merengue database (ModelClass, "file_name") """ sid = transaction.savepoint() try: models = set() for model_to_restore, file_name in models_to_restore: model_to_restore.objects.all().delete() # we first delete all objects to avoid duplication problems format = 'xml' fixtures_file_name = "%s.%s" % (file_name, format) fixtures_data = zip_config.read(fixtures_file_name) fixtures = serializers.deserialize(format, fixtures_data) has_objects = False for fixture in fixtures: if fixture: has_objects = True fixture.save() models.add(fixture.object.__class__) # HACK: If we found even one object in a fixture, we need to reset # the database sequences. if has_objects: sequence_reset_sql(models) except: transaction.savepoint_rollback(sid) raise else: transaction.savepoint_commit(sid)
def save(self, *args, **kwargs): if not self.pk and not self.slug: self.slug = self.slugify(self.name) using = kwargs.get("using") or router.db_for_write( type(self), instance=self) # Make sure we write to the same db for all attempted writes, # with a multi-master setup, theoretically we could try to # write and rollback on different DBs kwargs["using"] = using trans_kwargs = {"using": using} i = 0 while 1: i += 1 try: sid = transaction.savepoint(**trans_kwargs) res = super(TagBase, self).save(*args, **kwargs) transaction.savepoint_commit(sid, **trans_kwargs) except IntegrityError, e: if 'slug' not in e.message: raise transaction.savepoint_rollback(sid, **trans_kwargs) self.slug = self.slugify(self.name, i) else: return res
def test_force_update(self): c = Counter.objects.create(name="one", name2="ONE", value=1) # The normal case c.value = 2 c.save() # Same thing, via an update c.value = 3 c.save(force_update=True) # Won't work because force_update and force_insert are mutually # exclusive c.value = 4 self.assertRaises(ValueError, c.save, force_insert=True, force_update=True) # Try to update something that doesn't have a primary key in the first # place. c1 = Counter(name="two", name2="TWO", value=2) self.assertRaises(DatabaseError, c1.save, force_update=True) c1.save(force_insert=True) # Won't work because we can't insert a pk of the same value. sid = transaction.savepoint() c.value = 5 self.assertRaises(IntegrityError, c.save, force_insert=True) transaction.savepoint_rollback(sid) # Trying to update should still fail, even with manual primary keys, if # the data isn't in the database already. obj = WithCustomPK(name=1, value=1) self.assertRaises(DatabaseError, obj.save, force_update=True)
def create_qark(attrs=None): """ """ # Wrap the creation of the facet and its attributes in a transaction savepoint # and ensure that a transaction is active assert transaction.is_managed(), "A managed transaction is required to create a Fact" sid = transaction.savepoint() try: # Create a QArk and save it; make sure it is new qark = QArk(nextrev=1) qark.save(force_insert=True) # Look up the id's of any attributes specified by name # Find all of the Facets by looking up the attributes specified # Create each of the attributes for attrdict in attrs: # Create a QArkAttr and save it; make sure it's new; and add it to the QArk attr = QArkAttr.create_qarkattr(**attrdict) attr.qark = qark attr.rev = 0 attr.save(force_insert=True) return qark except: transaction.savepoint_rollback(sid) # TODO: Need an exception here that is meaningful to what went wrong raise else: transaction.savepoint_commit(sid)
def test_savepoint_rollback(self): """Tests rollbacks of savepoints""" from django.db import transaction from testapp.models import Genre, Publisher from johnny import cache if not connection.features.uses_savepoints: return self.failUnless(transaction.is_managed() == False) self.failUnless(transaction.is_dirty() == False) connection.queries = [] cache.local.clear() transaction.enter_transaction_management() transaction.managed() g = Genre.objects.get(pk=1) start_title = g.title g.title = "Adventures in Savepoint World" g.save() g = Genre.objects.get(pk=1) self.failUnless(g.title == "Adventures in Savepoint World") sid = transaction.savepoint() g.title = "In the Void" g.save() g = Genre.objects.get(pk=1) self.failUnless(g.title == "In the Void") transaction.savepoint_rollback(sid) g = Genre.objects.get(pk=1) self.failUnless(g.title == "Adventures in Savepoint World") transaction.rollback() g = Genre.objects.get(pk=1) self.failUnless(g.title == start_title) transaction.managed(False) transaction.leave_transaction_management()
def post(self, request): '''订单创建''' # 判断用户是否登录 user = request.user if not user.is_authenticated(): # 用户未登录 return JsonResponse({'res': 0, 'errmsg': '用户未登录'}) # 接收参数 addr_id = request.POST.get('addr_id') pay_method = request.POST.get('pay_method') sku_ids = request.POST.get('sku_ids') # 1,3 # 校验参数 if not all([addr_id, pay_method, sku_ids]): return JsonResponse({'res': 1, 'errmsg': '参数不完整'}) # 校验支付方式 try: pay_method = int(pay_method) except ValueError: return JsonResponse({'res': 2, 'errmsg': '非法的支付方式'}) if pay_method not in dict(OrderInfo.PAY_METHOD_CHOICES).keys(): return JsonResponse({'res': 2, 'errmsg': '非法的支付方式'}) # 校验地址 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: # 地址不存在 return JsonResponse({'res': 3, 'errmsg': '地址非法'}) # todo: 创建订单核心业务 # 组织参数 # 订单id: 20171122181630+用户id order_id = datetime.datetime.today().strftime('%Y%m%d%H%M%S') + str( user.id) # 运费 transit_price = 10 # 总数目和总金额 total_count = 0 total_price = 0 try: # 设置事务保存点 save_point = transaction.savepoint() # todo: 向df_order_info表中添加一条记录 order = OrderInfo.objects.create(order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price) # 模拟异常 # num = 1/0 # todo: 用户的订单中有几个商品,需要向df_order_goods表中加入几条记录 conn = settings.REDIS_CONN cart_key = 'cart_%d' % user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: for i in range(3): # 获取商品的信息 try: sku = GoodsSKU.objects.get(id=sku_id) except: # 回滚 transaction.savepoint_rollback(save_point) # 商品不存在 return JsonResponse({'res': 4, 'errmsg': '商品不存在'}) # 从redis中获取用户所要购买的商品的数量 count = conn.hget(cart_key, sku_id) # todo: 判断商品的库存 if int(count) > sku.stock: # 回滚 transaction.savepoint_rollback(save_point) return JsonResponse({'res': 6, 'errmsg': '商品库存不足'}) # todo: 更新商品的库存和销量 orgin_stock = sku.stock new_stock = orgin_stock - int(count) new_sales = sku.sales + int(count) # print('user:%d...stock:%d' % (user.id, sku.stock)) # import time # time.sleep(10) # 返回受影响的行数 update xxx where xxxx res = GoodsSKU.objects.filter( id=sku_id, stock=orgin_stock).update(stock=new_stock, sales=new_sales) if res == 0: if i == 2: transaction.savepoint_rollback(save_point) return JsonResponse({ 'res': 7, 'errmsg': '下单失败,并发' }) continue # todo: 向df_order_goods表中添加一条记录 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # # todo: 更新商品的库存和销量 # sku.stock -= int(count) # sku.sales += int(count) # sku.save() # todo: 累加计算订单商品的总数量和总价格 amount = sku.price * int(count) total_count += int(count) total_price += amount break # todo: 更新订单信息表中的商品的总数量和总价格 order.total_count = total_count order.total_price = total_price order.save() # 提交 transaction.savepoint_commit(save_point) except Exception as e: # 回滚 transaction.savepoint_rollback(save_point) print('1...') return JsonResponse({'res': 7, 'errmsg': '下单失败'}) # todo: 清除用户购物车中对应的记录 conn.hdel(cart_key, *sku_ids) # 返回应答 return JsonResponse({'res': 5, 'message': '创建成功'})
def import_data(self, dataset, dry_run=False, raise_errors=False, use_transactions=None, **kwargs): """ Imports data from ``tablib.Dataset``. Refer to :doc:`import_workflow` for a more complete description of the whole import process. :param dataset: A ``tablib.Dataset`` :param raise_errors: Whether errors should be printed to the end user or raised regularly. :param use_transactions: If ``True`` import process will be processed inside transaction. :param dry_run: If ``dry_run`` is set, or error occurs, transaction will be rolled back. """ result = Result() result.diff_headers = self.get_diff_headers() if use_transactions is None: use_transactions = self.get_use_transactions() if use_transactions is True: # when transactions are used we want to create/update/delete object # as transaction will be rolled back if dry_run is set real_dry_run = False sp1 = savepoint() else: real_dry_run = dry_run try: self.before_import(dataset, real_dry_run, **kwargs) except Exception as e: logging.exception(e) tb_info = traceback.format_exc() result.base_errors.append(Error(e, tb_info)) if raise_errors: if use_transactions: savepoint_rollback(sp1) raise instance_loader = self._meta.instance_loader_class(self, dataset) for row in dataset.dict: try: row_result = RowResult() instance, new = self.get_or_init_instance(instance_loader, row) if new: row_result.import_type = RowResult.IMPORT_TYPE_NEW else: row_result.import_type = RowResult.IMPORT_TYPE_UPDATE row_result.new_record = new original = deepcopy(instance) if self.for_delete(row, instance): if new: row_result.import_type = RowResult.IMPORT_TYPE_SKIP row_result.diff = self.get_diff( None, None, real_dry_run) else: row_result.import_type = RowResult.IMPORT_TYPE_DELETE self.delete_instance(instance, real_dry_run) row_result.diff = self.get_diff( original, None, real_dry_run) else: self.import_obj(instance, row, real_dry_run) if self.skip_row(instance, original): row_result.import_type = RowResult.IMPORT_TYPE_SKIP else: with transaction.atomic(): self.save_instance(instance, real_dry_run) self.save_m2m(instance, row, real_dry_run) # Add object info to RowResult for LogEntry row_result.object_repr = force_text(instance) row_result.object_id = instance.pk row_result.diff = self.get_diff(original, instance, real_dry_run) except Exception as e: # There is no point logging a transaction error for each row # when only the original error is likely to be relevant if not isinstance(e, TransactionManagementError): logging.exception(e) tb_info = traceback.format_exc() row_result.errors.append(Error(e, tb_info, row)) if raise_errors: if use_transactions: savepoint_rollback(sp1) six.reraise(*sys.exc_info()) if (row_result.import_type != RowResult.IMPORT_TYPE_SKIP or self._meta.report_skipped): result.rows.append(row_result) # Reset the SQL sequences when new objects are imported # Adapted from django's loaddata if not dry_run and any(r.import_type == RowResult.IMPORT_TYPE_NEW for r in result.rows): connection = connections[DEFAULT_DB_ALIAS] sequence_sql = connection.ops.sequence_reset_sql( no_style(), [self.Meta.model]) if sequence_sql: with connection.cursor() as cursor: for line in sequence_sql: cursor.execute(line) if use_transactions: if dry_run or result.has_errors(): savepoint_rollback(sp1) else: savepoint_commit(sp1) return result
def create_share_info(self, share_record, share_team, share_user, share_info): # 开启事务 sid = transaction.savepoint() try: # 删除历史数据 ServiceShareRecordEvent.objects.filter( record_id=share_record.ID).delete() RainbondCenterApp.objects.filter( record_id=share_record.ID).delete() app_templete = {} # 处理基本信息 try: app_templete["template_version"] = "v2" group_info = share_info["share_group_info"] app_templete["group_key"] = group_info["group_key"] app_templete["group_name"] = group_info["group_name"] app_templete["group_version"] = group_info["version"] except Exception as e: if sid: transaction.savepoint_rollback(sid) logger.exception(e) return 500, "基本信息处理错误", None # 处理插件相关,v3.5暂时不实现 try: # 确定分享的插件ID share_plugin_ids = {} plugins = share_info.get("share_plugin_list", None) if plugins: share_plugins = list() for plugin in plugins: version = plugin.get("build_version", "") plugin_id = plugin.get("plugin_id", "") if version and plugin_id: # 只有自己创建的插件需要分享出去 if plugin["origin"] == "source_code" and plugin[ "is_share"]: plugin_version = plugin_repo.get_plugin_buildversion( plugin_id, version) if plugin_version and plugin_version.plugin_version_status != "fixed": plugin_version.plugin_version_status = "fixed" plugin_version.save() plugin["config_groups"] = [ group.to_dict() for group in plugin_repo.get_plugin_config_groups( plugin_id, version) ] plugin["config_items"] = [ item.to_dict() for item in plugin_repo.get_plugin_config_items( plugin_id, version) ] plugin["version"] = plugin_version.to_dict() # TODO: 插件应该单独分享,此处暂时不处理,分享到应用内部 share_plugin_ids[plugin_id] = True share_plugins.append(plugin) app_templete["plugins"] = share_plugins except Exception as e: if sid: transaction.savepoint_rollback(sid) logger.exception(e) return 500, "插件处理发生错误", None # 处理应用相关 try: services = share_info["share_service_list"] if services: new_services = list() for service in services: image = service["image"] # 源码应用 if image.startswith("goodrain.me/runner") and service[ "language"] != "dockerfile": service[ 'service_slug'] = app_store.get_slug_connection_info( group_info["scope"], share_team.tenant_name) if not service['service_slug']: if sid: transaction.savepoint_rollback(sid) return 400, "获取源码包上传地址错误", None else: service[ "service_image"] = app_store.get_image_connection_info( group_info["scope"], share_team.tenant_name) if not service["service_image"]: if sid: transaction.savepoint_rollback(sid) return 400, "获取镜像上传地址错误", None if service.get("need_share", None): ssre = ServiceShareRecordEvent( team_id=share_team.tenant_id, service_key=service["service_key"], service_id=service["service_id"], service_name=service["service_cname"], service_alias=service["service_alias"], record_id=share_record.ID, team_name=share_team.tenant_name, event_status="not_start") ssre.save() new_services.append(service) # TODO:处理应用继承关系RainbondCenterAppInherit app_templete["apps"] = new_services else: if sid: transaction.savepoint_rollback(sid) return 400, "分享的应用信息不能为空", None except Exception as e: if sid: transaction.savepoint_rollback(sid) logger.exception(e) return 500, "应用信息处理发生错误", None # 删除同个应用组分享的相同版本 RainbondCenterApp.objects.filter( version=group_info["version"], tenant_service_group_id=share_record.group_id).delete() # 新增加 app = RainbondCenterApp( group_key=app_templete["group_key"], group_name=app_templete["group_name"], share_user=share_user.user_id, share_team=share_team.tenant_name, tenant_service_group_id=share_record.group_id, pic=group_info.get("pic", ""), source="local", record_id=share_record.ID, version=group_info["version"], scope=group_info["scope"], describe=group_info["describe"], app_template=json.dumps(app_templete)) app.save() share_record.step = 2 share_record.update_time = datetime.datetime.now() share_record.save() # 提交事务 if sid: transaction.savepoint_commit(sid) return 200, "分享信息处理成功", share_record.to_dict() except Exception as e: logger.exception(e) if sid: transaction.savepoint_rollback(sid) return 500, "应用分享处理发生错误", None
def sync_event(self, user, region_name, tenant_name, record_event): rc_apps = RainbondCenterApp.objects.filter( record_id=record_event.record_id) if not rc_apps: return 404, "分享的应用不存在", None rc_app = rc_apps[0] event_type = "share-yb" if rc_app.scope == "goodrain": event_type = "share-ys" event = self.create_publish_event(record_event, user.nick_name, event_type) record_event.event_id = event.event_id app_templetes = json.loads(rc_app.app_template) apps = app_templetes.get("apps", None) if not apps: return 500, "分享的应用信息获取失败", None new_apps = list() sid = transaction.savepoint() try: for app in apps: # 处理事件的应用 if app["service_key"] == record_event.service_key: body = { "service_key": app["service_key"], "app_version": rc_app.version, "event_id": event.event_id, "share_user": user.nick_name, "share_scope": rc_app.scope, "image_info": app.get("service_image", None), "slug_info": app.get("service_slug", None) } try: res, re_body = region_api.share_service( region_name, tenant_name, record_event.service_alias, body) bean = re_body.get("bean") if bean: record_event.region_share_id = bean.get( "share_id", None) record_event.event_id = bean.get("event_id", None) record_event.event_status = "start" record_event.update_time = datetime.datetime.now() record_event.save() image_name = bean.get("image_name", None) if image_name: app["share_image"] = image_name slug_path = bean.get("slug_path", None) if slug_path: app["share_slug_path"] = slug_path new_apps.append(app) else: transaction.savepoint_rollback(sid) return 400, "数据中心分享错误", None except Exception as e: logger.exception(e) transaction.savepoint_rollback(sid) if re_body: logger.error(re_body) return 500, "数据中心分享错误", None else: new_apps.append(app) app_templetes["apps"] = new_apps rc_app.app_template = json.dumps(app_templetes) rc_app.update_time = datetime.datetime.now() rc_app.save() transaction.savepoint_commit(sid) return 200, "数据中心分享开始", record_event except Exception as e: logger.exception(e) if sid: transaction.savepoint_rollback(sid) return 500, "应用分享介质同步发生错误", None
def post(self, request): print("123") # 登录判断 if not request.user.is_authenticated(): return JsonResponse({'code': 1, 'errmsg': '请先登录'}) # 获取请求参数:address_id, pay_method, sku_ids_str address_id = request.POST.get('address_id') pay_method = request.POST.get('pay_method') # 商品id,格式型如: 1,2,3 sku_ids_str = request.POST.get('sku_ids_str') # 校验参数不能为空 if not all([address_id, pay_method, sku_ids_str]): return JsonResponse({'code': 2, 'errmsg': '参数不完整'}) # 判断地址是否存在 try: address = Address.objects.get(id=address_id) except Address.DoesNotExist: return JsonResponse({'code': 3, 'errmsg': '地址不能为空'}) # 创建保存点 point = transaction.savepoint() try: # todo: 修改订单信息表: 保存订单数据到订单信息表中(新增一条数据) total_count = 0 total_amount = 0 trans_cost = 10 # 时间+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str( request.user.id) pay_method = int(pay_method) print("2") # order1 = None order = OrderInfo.objects.create( order_id=order_id, total_count=total_count, total_amount=total_amount, trans_cost=trans_cost, pay_method=pay_method, user=request.user, address=address, ) # print("1") # 获取StrictRedis对象: cart_1 = {1: 2, 2: 2} strict_redis = get_redis_connection() # type: StrictRedis key = 'cart_%s' % request.user.id sku_ids = sku_ids_str.split(',') # str ——> list # todo: 核心业务: 遍历每一个商品, 并保存到订单商品表 for sku_id in sku_ids: # 查询订单中的每一个商品对象 try: sku = GoodsSKU.objects.get(id=sku_id) except GoodsSKU.DoesNotExist: # 回滚动到保存点,撤销所有的sql操作 # transaction.savepoint_rollback(point) return JsonResponse({'code': 4, 'errmsg': '商品不存在'}) # 获取商品数量,并判断库存 count = strict_redis.hget(key, sku_id) count = int(count) # bytes -> int if count > sku.stock: # 回滚动到保存点,撤销所有的sql操作 # transaction.savepoint_rollback(point) return JsonResponse({'code': 5, 'errmsg': '库存不足'}) # todo: 修改订单商品表: 保存订单商品到订单商品表(新增多条数据) OrderGoods.objects.create( count=count, price=sku.price, order=order, sku=sku, ) # todo: 修改商品sku表: 减少商品库存, 增加商品销量 sku.stock -= count sku.sales += count sku.save() # 累加商品数量和总金额 total_count += count total_amount += sku.price * count # todo: 修改订单信息表: 修改商品总数量和总金额 order.total_count = total_count order.total_amount = total_amount order.save() except: # 回滚动到保存点,撤销所有的sql操作 transaction.savepoint_rollback(point) return JsonResponse({'code': 6, 'errmsg': '创建订单失败'}) # 提交事务(保存点) transaction.savepoint_commit(point) # 从Redis中删除购物车中的商品 # cart_1 = {1: 2, 2: 2} # redis命令: hdel cart_1 1 2 # 列表 -> 位置参数 strict_redis.hdel(key, *sku_ids) # 订单创建成功, 响应请求,返回json return JsonResponse({'code': 0, 'message': '创建订单成功'})
def create(self, validated_data): # 获取当前下单用户 user = self.context['request'].user # 生成订单编号 年月日时分秒+user.id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id) address = validated_data['address'] pay_method = validated_data['pay_method'] with transaction.atomic(): # 创建一个保存点 save_id = transaction.savepoint() try: # 创建订单信息 order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=0, total_amount=Decimal(0), freight=Decimal(10), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']) # 获取购物车信息 redis_conn = get_redis_connection('cart') redis_cart = redis_conn.hgetall('cart_%s' % user.id) cart_selected = redis_conn.smembers('cart_selected_%s' % user.id) # 将bytes类型转换成int类型 cart = {} for sku_id in cart_selected: cart[int(sku_id)] = int(redis_cart[sku_id]) # 一次查询出所有商品数据 skus = SKU.objects.filter(id__in=cart.keys()) # 处理订单商品 for sku in skus: sku_count = cart[sku.id] # 判断库存 origin_stock = sku.stock origin_sales = sku.sales if sku_count > origin_stock: transaction.savepoint_rollback(save_id) raise serializers.ValidationError('商品库存不足') # new_stock = origin_stock - sku_count # new_sales = origin_sales + sku_count # # sku.stock = new_stock # sku.sales = new_sales # sku.save() # 用于演示并发下单 # time.sleep(5) new_stock = origin_stock - sku_count new_sales = origin_sales + sku_count # 根据原始库存条件更新,返回更新的条目数,乐观锁 ret = SKU.objects.filter( id=sku.id, stock=origin_stock).update(stock=new_stock, sales=new_sales) if ret == 0: raise serializers.ValidationError('库存不足') # 累计商品的SPU销量信息 sku.goods.sales += sku_count sku.goods.save() # 累计订单基本信息的数据 order.total_count += sku_count order.total_amount += (sku.price * sku_count) # 保存订单商品 OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 更新订单的金额数量信息 order.total_amount += order.freight order.save() except ValidationError: raise except Exception as e: transaction.savepoint_rollback(save_id) raise transaction.savepoint_commit(save_id) # 更新redis中保存的购物车数据 pl = redis_conn.pipeline() pl.hdel('cart_%s' % user.id, *cart_selected) pl.srem('cart_selected_%s' % user.id, *cart_selected) pl.execute() return order
def create(self, validated_data): """保存订单信息(订单并发-悲观锁)""" # 获取参数address和pay_method address = validated_data['address'] pay_method = validated_data['pay_method'] # 组织参数 # 用户user user = self.context['request'].user # 订单id: '年月日时分秒'+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%010d' % user.id) # 运费 freight = Decimal(10) # 订单商品总数量和实付款 total_count = 0 total_amount = Decimal(0) # 订单状态 # if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']: # # 货到付款 # status = OrderInfo.ORDER_STATUS_ENUM['UNSEND'] # 待发货 # else: # # 在线支付 # status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] # 待支付 status = OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID'] # 获取redis链接 redis_conn = get_redis_connection('cart') # 从redis中获取用户所要购买的商品sku_id set cart_selected_key = 'cart_selected_%s' % user.id # (b'<sku_id>', ...) sku_ids = redis_conn.smembers(cart_selected_key) # 从redis中获取用户购物车商品的sku_id和对应的数量count hash cart_key = 'cart_%s' % user.id # { # b'<sku_id>': b'<count>', # ... # } cart_dict = redis_conn.hgetall(cart_key) with transaction.atomic(): # 在with语句块中代码,凡是涉及到数据库操作的代码,都会放到同一个事务中 # 设置一个事务保存点 sid = transaction.savepoint() try: # 1)向订单基本信息表添加一条记录 order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=total_count, total_amount=total_amount, freight=freight, pay_method=pay_method, status=status ) # 2)订单中包含几个商品,就需要向订单商品表中添加几条记录 for sku_id in sku_ids: # 获取用户所要购买的该商品的数量count count = cart_dict[sku_id] count = int(count) for i in range(3): # 根据sku_id获取商品信息 # select * from tb_sku where id=<sku_id>; sku = SKU.objects.get(id=sku_id) # 判断商品库存是否充足 if count > sku.stock: # 回滚到sid事务保存点 transaction.savepoint_rollback(sid) raise serializers.ValidationError('商品库存不足') # 记录商品原始库存 origin_stock = sku.stock new_stock = origin_stock - count new_sales = sku.sales + count # 模拟订单并发问题 # print('user: %d times: %s stock: %s' % (user.id, i, origin_stock)) # import time # time.sleep(10) # 减少商品库存,增加销量 # update tb_sku # set stock=<new_stock>, sales=<new_sales> # where id=<sku_id> and stock=<origin_stock>; # update方法返回的是更新的行数 res = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales) if res == 0: if i == 2: # 更新了3次,仍然失败,下单失败 # 回滚到sid事务保存点 transaction.savepoint_rollback(sid) raise serializers.ValidationError('下单失败2') # 更新失败,重新进行尝试 continue # 向订单商品表中添加一条记录 OrderGoods.objects.create( order=order, sku=sku, count=count, price=sku.price ) # 累加计算订单中商品总数量和总金额 total_count += count total_amount += sku.price*count # 更新成功,跳出循环 break # 实付款 total_amount += freight # 更新订单记录中商品的总数量和实付款 order.total_count = total_count order.total_amount = total_amount order.save() except serializers.ValidationError: # 继续向外抛出异常 raise except Exception as e: # 回滚sid事务保存点 transaction.savepoint_rollback(sid) raise serializers.ValidationError('下单失败1') # 3)清除购物车中对应的记录 pl = redis_conn.pipeline() pl.hdel(cart_key, *sku_ids) pl.srem(cart_selected_key, *sku_ids) pl.execute() # 返回订单对象 return order
def OrderCommit(requset): if requset.method == 'POST': user = requset.user if not user.is_authenticated(): # 用户未登录 return JsonResponse({'res': 0, 'errmsg': '用户未登录'}) # 接收参数 addr_id = requset.POST.get('addr_id') pay_method = requset.POST.get('pay_method') sku_ids = requset.POST.get('sku_ids') # 检验参数 if not all([addr_id, pay_method, sku_ids]): return JsonResponse({'res': 1, 'errmsg': '参数不完整'}) # 校验支付方式 if pay_method not in OrderInfo.PAY_METHODS.keys(): return JsonResponse({'res': 2, 'errmsg': '非法的支付方式'}) # 校验地址 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: # 地址不存在 return JsonResponse({'res': 3, 'errmsg': '地址不存在'}) # todo:创建订单核心业务 # 组织参数 # 订单id:20171122181630+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id) # 运费 transit_price = 10 # 总数目和总价格 total_count = 0 total_price = 0 # 设置事务保存点 save_id = transaction.savepoint() try: # todo:向df_order_info表中添加一条记录 order = OrderInfo.objects.create(order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price) # todo:用户的订单中有几个商品,需要向df_order_goods表中加入几条记录 conn = settings.REDIS_CONN cart_key = 'cart_%d' % user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: for i in range(3): # 获取商品的信息 try: # 解决订单并发情况(悲观锁) # select * from df_goods_sku where id=sku_id for update;加锁 # sku = GoodsSKU.objects.select_for_update().get(id=sku_id) sku = GoodsSKU.objects.get(id=sku_id) except: # 商品不存在 transaction.savepoint_rollback(save_id) # 回滚到保存点 return JsonResponse({'res': 4, 'errmsg': '商品不存在'}) # 从redis中获取用户所要购买商品的数量 count = conn.hget(cart_key, sku_id) # todo:判断商品的库存 if int(count) > sku.stock: transaction.savepoint_rollback(save_id) # 回滚到保存点 return JsonResponse({'res': 6, 'errmsg': '商品库存不足'}) # todo:更新商品的库存和销量 orgin_stock = sku.stock new_stock = orgin_stock - int(count) new_sales = sku.sales + int(count) # print('user:%d times:%d stock:%d'%(user.id, i, sku.stock)) # import time # time.sleep(5) # 解决订单并发情况(乐观锁:冲突较少或者重复操作的代价大的时候使用) # update df_goods_Sku set stock=new_stock, sales=new_sales # where id=sku_id and stock=orgin_Stock # 返回受影响的行数 res = GoodsSKU.objects.filter( id=sku_id, stock=orgin_stock).update(stock=new_stock, sales=new_sales) if res == 0: if i == 2: # 尝试的第三次没有成功的话->下单失败 transaction.savepoint_rollback(sku_id) return JsonResponse({'res': 7, 'errmsg': '下单失败2'}) continue # todo:向df_order_goods表中添加一条记录 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # todo:累加计算订单商品的总数量和总价格 amount = sku.price * int(count) total_count += int(count) total_price += amount # 跳出循环进行后面操作 break # todo:更新订单信息表中的商品总数量和总价格 order.total_count = total_count order.total_price = total_price order.save() except Exception as e: transaction.savepoint_rollback(save_id) # 回滚到保存点 return JsonResponse({'res': 7, 'errmsg': '下单失败'}) # 提交事务 transaction.savepoint_commit(save_id) # todo:清除用户购物车中对应的记录 conn.hdel(cart_key, *sku_ids) # 返回应答 return JsonResponse({'res': 5, 'message': '创建成功'})
def import_invoice_sheet(worksheet, invoice_reference=None, customer_2_id_dict=None, producer=None): error = False error_msg = None header = get_header(worksheet) if header: now = timezone.now().date() lut_reverse_vat = dict(LUT_ALL_VAT_REVERSE) import_counter = 0 row_num = 1 sid = transaction.savepoint() try: permanence = Permanence.objects.create( permanence_date=now, short_name=invoice_reference, status=PERMANENCE_SEND, highest_status=PERMANENCE_SEND) permanence.producers.add(producer) row = get_row(worksheet, header, row_num) while row and not error: customer_name = row[_("Customer")] if customer_name: if customer_name in customer_2_id_dict: customer_id = customer_2_id_dict[customer_name] else: error = True error_msg = _( "Row %(row_num)d : No valid customer") % { 'row_num': row_num + 1 } break product_reference = row[_("Reference")] unit = row[_("Unit")] order_unit = get_reverse_invoice_unit(unit) vat = row[_("VAT level")] vat_level = lut_reverse_vat[vat] product = Product.objects.filter( producer_id=producer.id, reference=product_reference).order_by('?').first() if product is None: product = Product.objects.create( producer=producer, reference=product_reference, ) product.long_name = row[_("Product")] # The producer unit price is the imported customer unit price # If the group get a reduction, this one must be mentionned into the producer admin screen # into the "price_list_multiplier" field product.producer_unit_price = row[_("Customer unit price")] product.unit_deposit = row[_("Deposit")] product.order_unit = order_unit product.vat_level = vat_level product.wrapped = row[_("Wrapped")] product.save() qty_and_price_display = product.get_qty_and_price_display( customer_price=False) if product.long_name.endswith(qty_and_price_display): product.long_name = product.long_name[:-len( qty_and_price_display)] product.save() offer_item = product.get_or_create_offer_item( permanence, reset_add_2_stock=True) create_or_update_one_purchase(customer_id, offer_item, q_order=Decimal( row[_("Quantity")]), status=PERMANENCE_SEND, batch_job=True, is_box_content=False, comment=row[_("Comment")]) import_counter += 1 row_num += 1 row = get_row(worksheet, header, row_num) reorder_offer_items(permanence.id) reorder_purchases(permanence.id) except KeyError as e: # Missing field error = True error_msg = _( "Row %(row_num)d : A required column is missing %(error_msg)s." ) % { 'row_num': row_num + 1, 'error_msg': str(e) } except Exception as e: error = True error_msg = _("Row %(row_num)d : %(error_msg)s.") % { 'row_num': row_num + 1, 'error_msg': str(e) } if not error and import_counter == 0: error = True error_msg = "{}".format(_("Nothing to import.")) if error: transaction.savepoint_rollback(sid) else: transaction.savepoint_commit(sid) return error, error_msg
def post(self, request): # 1、提取参数 data = json.loads(request.body.decode()) address_id = data.get('address_id') pay_method = data.get('pay_method') # 2、校验参数 if not all([address_id, pay_method]): return JsonResponse({'code': 400, 'errmsg': '缺少参数'}) try: address = Address.objects.get(pk=address_id) except Address.DoesNotExist as e: return JsonResponse({'code': 400, 'errmsg': '地址不存在'}) # OrderInfo.PAY_METHODS_ENUM.values() --> [1, 2] if pay_method not in [ OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY'] ]: return JsonResponse({'code': 400, 'errmsg': '支付方式不支持'}) # 3、业务数据处理 user = request.user # 约定购物车字典格式数据 cart_dict = {} # {1: {"count": 5, "selected": True}} # 获取redis购物车数据 conn = get_redis_connection('carts') redis_carts = conn.hgetall('carts_%s' % user.id) # {b'1': b'5'} redis_selected = conn.smembers('selected_%s' % user.id) # [b'1'] sku_ids = redis_carts.keys() for sku_id in sku_ids: if sku_id in redis_selected: cart_dict[int(sku_id)] = { 'count': int(redis_carts[sku_id]), 'selected': sku_id in redis_selected # True } # 3.1、新建订单 —— OrderInfo cur_time = timezone.localtime() # cur_time.strftime('%Y%m%d%H%M%S') # '20201224111256' # order_id = '20201224111256' + "00000005" order_id = cur_time.strftime('%Y%m%d%H%M%S') + "%08d" % user.id with transaction.atomic(): # (1)、设置一个保存点 —— 用于回滚 save_id = transaction.savepoint() order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, # address_id = address_id total_count=0, # 初始化为0,后续统计订单商品的时候在修改 total_amount=Decimal('0'), freight=Decimal('10.0'), # 运费 pay_method=pay_method, # 支付方式 # 如果用户选择支付宝,状态为未支付;如果用户选择货到付款,状态未未发货。 status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND'] ) # 3.2、新建订单商品(就是用户redis购物车中选中的sku商品) —— OrderGoods sku_selected_ids = cart_dict.keys() # 所有已经选中的商品的id for sku_id in sku_selected_ids: # sku_id是每一个被选中的sku的id count = cart_dict[sku_id]['count'] # 用户购买量 while True: # (1)、读取旧库存和销量数据 sku = SKU.objects.get(pk=sku_id) old_stock = sku.stock # 旧库存 old_sales = sku.sales # 旧销量 # (2)、计算新库存和销量 new_stock = old_stock - count new_sales = old_sales + count # (3)、基于旧数据查找,并更新 # update函数返回值为一个整数表示受影响的数据条数 result = SKU.objects.filter( pk=sku_id, stock=old_stock, sales=old_sales ).update( stock=new_stock, sales=new_sales ) if result == 0: # 如果result为0,说明没有数据被更新,说明filter没有过滤出任何数据,说明旧数据发生改变,说明有别的事务介入 continue # result不为0,表示基于旧数据查找并成功更新库存和销量,针对此次sku的更新完成,跳出循环 break # TODO: 判断库存 if count > old_stock: # 库存不够 —— 下单失败 # (2)、回滚事务,到新建订单order之前的保存点 transaction.savepoint_rollback(save_id) return JsonResponse({'code': 400, 'errmsg': '%s,%d 库存不够' % (sku.name, sku.id)}) # 新建OrderGoods对象保存数据库 OrderGoods.objects.create( order=order, sku=sku, count=count, price=sku.price, # 单价 ) spu = sku.spu # 当前sku关联的spu spu.sales += count spu.save() # 更新订单的商品数量和总价格 order.total_count += count order.total_amount += sku.price * count order.total_amount += order.freight # 把运费累加到总价中 order.save() # (3)、删除保存点 transaction.savepoint_commit(save_id) # TODO: 清楚已经下单的购物车商品 conn.hdel('carts_%s' % user.id, *sku_selected_ids) # func(*[1,2]) --> func(1,2) conn.srem('selected_%s' % user.id, *sku_selected_ids) # 4、构建响应 return JsonResponse({'code': 0, 'errmsg': 'ok', 'order_id': order_id})
def post(self, request): # 1.接收非表单 参数 json_dict = json.loads(request.body.decode()) address_id = json_dict.get('address_id') pay_method = json_dict.get('pay_method') # 2.校验参数 try: address = Address.objects.get(pk=address_id) except: return http.HttpResponseNotFound('地址不存在!') # 校验支付方式 : 1.支付宝 alipay 2.货到付款 cash if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]: return http.HttpResponseForbidden('美多商城暂不支持{}支付方式'.format(pay_method)) # 3. 新增 OrderInfo 添加数据 user = request.user # 年月日 时分秒 + 9个0 + user.id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ("%09d" % user.id) # 添加 局部 事务 from django.db import transaction with transaction.atomic(): # 设置 事务开始点-- 保存点 sid = transaction.savepoint() try: order = OrderInfo.objects.create(order_id=order_id, user=user, address_id=address.id, freight=Decimal('10.00'), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'], total_count=0, total_amount=Decimal('0.00')) # 4. 新增 OrderGoods 添加数据-- # - 已经选中的商品SKU---redis client = get_redis_connection('carts') redis_carts = client.hgetall(user.id) selected_dict = {} for k, v in redis_carts.items(): sku_id = int(k.decode()) sku_dict = json.loads(v.decode()) # 选中的商品 True if sku_dict['selected']: selected_dict[sku_id] = sku_dict for sku_id in selected_dict.keys(): while True: # 当前购买的 sku的 所有信息--时时信息 sku = SKU.objects.get(pk=sku_id) # 获取老库存 和 老销量 origin_stock = sku.stock origin_sale = sku.sales cart_count = selected_dict.get(sku_id).get('count') # 判断库存 ; 购买个数 大于> sku的库存stock if cart_count > sku.stock: # 事务回滚 transaction.savepoint_rollback(sid) return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '{}-库存不足!'.format(sku.name)}) # 加延迟 10s中---测试 并发下单 # time.sleep(10) # sku 库存减少 销量增加 # sku.stock -= cart_count # sku.sales += cart_count # sku.save() # 计算 将来修改的 库存 和销量只 ---加锁 new_stock = origin_stock - cart_count new_sales = origin_sale + cart_count result=SKU.objects.filter(id=sku.id, stock=origin_stock).update(stock=new_stock, sales=new_sales) # 如果 库存非常充足, 只是 在下单的时候 老库存修改了, 应该是 能够下单成功的---内部自动继续下单 if result == 0: continue # spu 销量增加 sku.spu.sales += cart_count sku.spu.save() # 订单商品表的 必传字段 填写全了 OrderGoods.objects.create(order=order,sku=sku, count=cart_count, price=sku.price ) # 计算 总计金额 总个数 order.total_count += cart_count order.total_amount += sku.price * cart_count # 下单成功--跳出循环 break # 最后 总的 支付金额 == 累加金额 + 运费 order.total_amount += order.freight order.save() except Exception as e: logger.error(e) # 事务回滚 transaction.savepoint_rollback(sid) # 返回响应对象 return http.JsonResponse({'code': 0, 'errmsg': '下单失败了'}) # 事务提交 transaction.savepoint_commit(sid) # 清空redis数据库 中选中的商品 client.hdel(user.id, *selected_dict) # 返回响应对象 return http.JsonResponse({'code': 0, 'errmsg': '下单成功', 'order_id': order.order_id})
def handle(self, *args, **options): accountings = [] period = models.PeriodeBudget.active.first() self.errors = [] # Structure du fichier : # Année # Structure # Plan de financement # Dépense/recette # Enveloppe # Nature comptable # Domaine fonctionnel # AE # CP # Charges/immos # AR # RE # Produits/ressources # Commentaire structures = { s.code: s for s in structure_models.Structure.active.all() } pfis = { pfi.code: pfi for pfi in structure_models.PlanFinancement.active.all() } dan = {(an.code_nature_comptable, an.is_fleche): an for an in structure_models.NatureComptableDepense.active.all()} ran = {(an.code_nature_comptable, an.is_fleche): an for an in structure_models.NatureComptableRecette.active.all()} domains = { d.code: d for d in structure_models.DomaineFonctionnel.active.all() } for filename in options.get('filename'): # Detect charset with chardet ? # Windows encoding with open(filename, encoding='iso-8859-1') as h: reader = csv.reader(h, delimiter=';', quotechar='"') for index, row in enumerate(reader): if index == 0: # Ignore header continue try: (year, structure, pfi, accounting_type, enveloppe, nature, domain, ae, cp, d_dc, ar, re, r_dc, commentary) = row pfi = self.get_object(pfis, pfi, 'PFI') if accounting_type.lower().startswith('d'): # Dépense model = models.Depense nature = self.get_object(dan, (nature, pfi.is_fleche), 'nature') functional_domain = self.get_object( domains, domain, 'domaine fonctionnel', msg=f'- nature : {nature}') amounts = { 'montant_dc': to_decimal(d_dc), 'montant_cp': to_decimal(cp), 'montant_ae': to_decimal(ae), 'naturecomptabledepense': nature, 'domainefonctionnel': functional_domain, } else: # Recette model = models.Recette nature = self.get_object(ran, (nature, pfi.is_fleche), 'nature') amounts = { 'montant_dc': to_decimal(r_dc), 'montant_re': to_decimal(re), 'montant_ar': to_decimal(ar), 'naturecomptablerecette': nature, 'domainefonctionnel': domain, } structure = self.get_object(structures, structure, 'structure') accountings.append( model(pfi=pfi, structure=structure, commentaire=commentary or None, periodebudget=period, annee=year, **amounts)) except RowError: continue if self.errors: print('ERRORS :\n\n{}'.format('\n'.join(self.errors))) else: sid = transaction.savepoint() try: for obj in accountings: obj.save() print(f'{len(accountings)} accountings created') except Exception as e: print(f'Exception on save : {e}') transaction.savepoint_rollback(sid) else: transaction.savepoint_commit(sid)
def post(self, request): '''订单创建''' #判断用户是否登陆 user = request.user if not user.is_authenticated: #用户未登陆 return JsonResponse({'res': 0, 'errmsg': '用户未登录'}) #接收参数 addr_id = request.POST.get('addr_id') pay_method = request.POST.get('pay_method') sku_ids = request.POST.get('sku_ids') #校验参数 if not all((addr_id, pay_method, sku_ids)): return JsonResponse({'res': 1, 'errmsg': '参数不完整'}) #校验支付方式 if pay_method not in OrderInfo.PAY_METHODS.keys(): return JsonResponse({'res': 2, 'errmsg': '无效的支付方式'}) #校验地址 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: #地址不存在 return JsonResponse({'res': 3, 'errmsg': '地址非法'}) #todo:创建订单核心业务 #订单信息表:df_order_info,订单商品表:df_order_goods #todo:用户每下一个订单,就需要向df_order_info表中加入一条记录,用户订单中有几个商品就需要向df_order_goods表中加入几条记录 #组织参数 #订单id:20200103+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id) #运费 transit_price = 10 #总数目和总金额 total_count = 0 total_price = 0 #设置事物保存点 save_id = transaction.savepoint() #todo:向df_order_info表中添加一条记录 try: # todo: 向df_order_info表中添加一条记录 order = OrderInfo.objects.create(order_id=order_id, user=user, address=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price) # todo: 向df_order_goods表中添加记录 conn = get_redis_connection('default') cart_key = 'cart_{0}'.format(user.id) sku_ids = sku_ids.split(',') for sku_id in sku_ids: # 使用乐观锁,需多重复几次,需要数据库的隔离级别为:提交读Read committed。 for i in range(3): # 获取商品信息 try: sku = GoodsSKU.objects.get(id=sku_id) except Exception as e: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 4, 'errmsg': '商品不存在'}) # 从redis中获取商品的数量 count = conn.hget(cart_key, sku_id) # todo: 判断某一个商品的库存 if int(count) > sku.stock: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 6, 'errmsg': '商品库存不足'}) # todo: 更新商品的库存和销量 orgin_stock = sku.stock orgin_sales = sku.sales new_stock = orgin_stock - int(count) new_sales = orgin_sales + int(count) # 加乐观锁 # update df_goods_sku set stock=new_stock, sales=new_sales # where id=sku_id and stock=orgin_stock; res = GoodsSKU.objects.filter( id=sku_id, stock=orgin_stock).update(stock=new_stock, sales=new_sales) if res == 0: if i == 2: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 7, 'errmsg': '下单失败2'}) continue # todo: 向df_order_goods表中添加一条记录 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # todo: 累加计算订单商品的总数量和总价格 amount = sku.price * int(count) total_count += int(count) total_price += amount # 如果成功了,跳出循环 break # todo: 更新订单信息表中的商品的总数量和总价格 order.total_price = total_price order.total_count = total_count order.save() except Exception as e: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 7, 'errmsg': '下单失败'}) #提交事务 transaction.savepoint_commit(save_id) #todo:清除用户购物车中对应的记录[1,3] conn.hdel(cart_key, *sku_ids) #返回应答 return JsonResponse({'res': 5, 'message': '创建成功'})
def post(self, request): """保存订单信息和订单商品信息""" # 获取当前保存订单时需要的信息 # 接收参数 json_dict = json.loads(request.body.decode()) address_id = json_dict.get("address_id") pay_method = json_dict.get("pay_method") pay_method = int(pay_method) # 校验参数 if not all([address_id, pay_method]): return http.HttpResponseForbidden('缺少必传参数') # 判断address_id是否合法 try: address = Address.objects.get(id=address_id) except Exception: return http.HttpResponseForbidden('参数address_id错误') # 判断pay_method是否合法 if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]: return http.HttpResponseForbidden('参数pay_method错误') # 显式的开启一个事务 from django.db import transaction # 设置事物起始 with transaction.atomic(): # 事物保存点 save_id = transaction.savepoint() try: # 1.保存订单基本信息 user = request.user # 生成订单编号 年月日时分秒 + 9位用户编号 order_id = datetime.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id) # 保存订单基本信息 order = OrderInfo.objects.create( order_id=order_id, user=user, address= address, total_count=0, total_amount=Decimal('0'), freight=Decimal('10.00'), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[ 'ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND'] ) # 2.保存相关商品信息 # 从购物车 取出选中的商品 redis_client = get_redis_connection('carts') carts_data = redis_client.hgetall(user.id) carts_dict = {} for data in carts_data.items(): sku_id = int(data[0].decode()) sku_dict = json.loads(data[1].decode()) if sku_dict['selected']: carts_dict[sku_id] = sku_dict # 遍历 商品信息 sku_ids = carts_dict.keys() for sku_id in sku_ids: while True: sku = SKU.objects.get(id=sku_id) # 原始销量 和 库存量 origin_sales = sku.sales origin_stock = sku.stock # 判断库存是否充足 sku_count = carts_dict[sku_id]['count'] if sku_count > sku.stock: # 事物回滚 transaction.savepoint_rollback(save_id) return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'}) # 模拟资源抢夺 # time.sleep(10) # sku减少库存, 增加销量 # sku.stock -= sku_count # sku.sales += sku_count # sku.save() # 使用乐观锁 更新库存量 new_stock = origin_stock - sku_count new_sales = origin_sales + sku_count result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales) # 如果下单下单失败,库存足够则继续下单,直到下单成功或者库存不足 if result == 0: continue else: # SPU 增加销量 sku.spu.sales += sku_count sku.spu.save() # 保存订单商品信息 OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 保存商品订单中总价和总数量 order.total_count += sku_count order.total_amount += (sku_count * sku.price) # 下单成功 或失败跳出 break # 添加邮费和保存订单 order.total_amount += order.freight order.save() except: # 事物回滚 transaction.savepoint_rollback(save_id) return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败'}) # 提交事物 transaction.savepoint_commit(save_id) # 清除购物车已经结算过的商品 redis_client.hdel(user.id, *carts_dict) # 返回响应结果 return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})
def do_import(request, import_log_id): """ Import the data! """ import_log = get_object_or_404(ImportLog, id=import_log_id) if import_log.import_type == "N" and 'undo' in request.GET and request.GET['undo'] == "True": import_log.undo() return HttpResponseRedirect(reverse( 'simple_import:simple_import-do_import', kwargs={'import_log_id': import_log.id}) + '?success_undo=True') if 'success_undo' in request.GET and request.GET['success_undo'] == "True": success_undo = True else: success_undo = False model_class = import_log.import_setting.content_type.model_class() import_data = import_log.get_import_file_as_list() header_row = import_data.pop(0) header_row_field_names = [] header_row_default = [] header_row_null_on_empty = [] error_data = [header_row + ['Error Type', 'Error Details']] create_count = 0 update_count = 0 fail_count = 0 if 'commit' in request.GET and request.GET['commit'] == "True": commit = True else: commit = False key_column_name = None if import_log.update_key and import_log.import_type in ["U", "O"]: key_match = import_log.import_setting.columnmatch_set.get(column_name=import_log.update_key) key_column_name = key_match.column_name key_field_name = key_match.field_name for i, cell in enumerate(header_row): match = import_log.import_setting.columnmatch_set.get(column_name=cell) header_row_field_names += [match.field_name] header_row_default += [match.default_value] header_row_null_on_empty += [match.null_on_empty] if key_column_name != None and key_column_name.lower() == cell.lower(): key_index = i with transaction.atomic(): sid = transaction.savepoint() for row in import_data: try: with transaction.atomic(): is_created = True if import_log.import_type == "N": new_object = model_class() elif import_log.import_type == "O": filters = {key_field_name: row[key_index]} new_object = model_class.objects.get(**filters) is_created = False elif import_log.import_type == "U": filters = {key_field_name: row[key_index]} new_object = model_class.objects.filter(**filters).first() if new_object == None: new_object = model_class() is_created = False new_object.simple_import_m2ms = {} # Need to deal with these after saving for i, cell in enumerate(row): if header_row_field_names[i]: # skip blank if not import_log.is_empty(cell) or header_row_null_on_empty[i]: set_field_from_cell(import_log, new_object, header_row_field_names[i], cell) elif header_row_default[i]: set_field_from_cell(import_log, new_object, header_row_field_names[i], header_row_default[i]) new_object.save() for i, cell in enumerate(row): if header_row_field_names[i]: # skip blank if not import_log.is_empty(cell) or header_row_null_on_empty[i]: set_method_from_cell(import_log, new_object, header_row_field_names[i], cell) elif header_row_default[i]: set_method_from_cell(import_log, new_object, header_row_field_names[i], header_row_default[i]) new_object.save() for key in new_object.simple_import_m2ms.keys(): value = new_object.simple_import_m2ms[key] m2m = getattr(new_object, key) m2m_model = type(m2m.model()) related_field_name = RelationalMatch.objects.get(import_log=import_log, field_name=key).related_field_name m2m_object = m2m_model.objects.get(**{related_field_name:value}) m2m.add(m2m_object) if is_created: LogEntry.objects.log_action( user_id = request.user.pk, content_type_id = ContentType.objects.get_for_model(new_object).pk, object_id = new_object.pk, object_repr = smart_text(new_object), action_flag = ADDITION ) create_count += 1 else: LogEntry.objects.log_action( user_id = request.user.pk, content_type_id = ContentType.objects.get_for_model(new_object).pk, object_id = new_object.pk, object_repr = smart_text(new_object), action_flag = CHANGE ) update_count += 1 ImportedObject.objects.create( import_log = import_log, object_id = new_object.pk, content_type = import_log.import_setting.content_type) except IntegrityError: exc = sys.exc_info() error_data += [row + ["Integrity Error", smart_text(exc[1])]] fail_count += 1 except ObjectDoesNotExist: exc = sys.exc_info() error_data += [row + ["No Record Found to Update", smart_text(exc[1])]] fail_count += 1 except ValueError: exc = sys.exc_info() if str(exc[1]).startswith('invalid literal for int() with base 10'): error_data += [row + ["Incompatible Data - A number was expected, but a character was used", smart_text(exc[1])]] else: error_data += [row + ["Value Error", smart_text(exc[1])]] fail_count += 1 except: error_data += [row + ["Unknown Error"]] fail_count += 1 if not commit: transaction.savepoint_rollback(sid) if fail_count: from io import StringIO from django.core.files.base import ContentFile from openpyxl.workbook import Workbook from openpyxl.writer.excel import save_virtual_workbook wb = Workbook() ws = wb.worksheets[0] ws.title = "Errors" filename = 'Errors.xlsx' for row in error_data: ws.append(row) buf = StringIO() # Not Python 3 compatible #buf.write(str(save_virtual_workbook(wb))) import_log.error_file.save(filename, ContentFile(save_virtual_workbook(wb))) import_log.save() return render( request, 'simple_import/do_import.html', { 'error_data': error_data, 'create_count': create_count, 'update_count': update_count, 'fail_count': fail_count, 'import_log': import_log, 'commit': commit, 'success_undo': success_undo,}, )
def post(self, request): '''订单创建''' #判断用户是否登陆 user = request.user if not user.is_authenticated: #用户未登陆 return JsonResponse({'res': 0, 'errmsg': '用户未登录'}) #接收参数 addr_id = request.POST.get('addr_id') pay_method = request.POST.get('pay_method') sku_ids = request.POST.get('sku_ids') #校验参数 if not all((addr_id, pay_method, sku_ids)): return JsonResponse({'res': 1, 'errmsg': '参数不完整'}) #校验支付方式 if pay_method not in OrderInfo.PAY_METHODS.keys(): return JsonResponse({'res': 2, 'errmsg': '无效的支付方式'}) #校验地址 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: #地址不存在 return JsonResponse({'res': 3, 'errmsg': '地址非法'}) #todo:创建订单核心业务 #订单信息表:df_order_info,订单商品表:df_order_goods #todo:用户每下一个订单,就需要向df_order_info表中加入一条记录,用户订单中有几个商品就需要向df_order_goods表中加入几条记录 #组织参数 #订单id:20200103+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id) #运费 transit_price = 10 #总数目和总金额 total_count = 0 total_price = 0 #设置事物保存点 save_id = transaction.savepoint() #todo:向df_order_info表中添加一条记录 try: order = OrderInfo.objects.create( order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price, ) #todo:用户的订单中有几个商品,需要向df_order_goods表中加入几条记录 conn = get_redis_connection('default') cart_key = 'cart_%s' % user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: #获取商品信息 try: #悲观锁加锁 #select * from df_goods_sku where id=sku_id for update; sku = GoodsSKU.objects.select_for_update().get(id=sku_id) except: #商品不存在 transaction.savepoint_rollback(save_id) return JsonResponse({'res': 4, 'errmsg': '商品不存在'}) #从redis中获取用户所要购买的商品数量 count = conn.hget(cart_key, sku_id) #todo:判断商品的库存 if int(count) > sku.stock: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 6, 'errmsg': '商品库存不足'}) #todo:向df_order_goods表中添加一条记录 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) #todo:更新商品的库存和销量 sku.stock -= int(count) sku.sales += int(count) sku.save() #todo:累加计算订单商品的总数量和总价格 amount = sku.price * int(count) total_count += int(count) total_price += amount #todo:更新订单信息表中的商品的总数量和总价格 order.total_price = total_price order.total_count = total_count order.save() except Exception as e: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 7, 'errmsg': '下单失败'}) #提交事务 transaction.savepoint_commit(save_id) #todo:清除用户购物车中对应的记录[1,3] conn.hdel(cart_key, *sku_ids) #返回应答 return JsonResponse({'res': 5, 'message': '创建成功'})
def post(self, request): """ 1. 收货地址address_id 2. 商品sku_ids(多个 request.POST.getlist("sku_ids")) 3. 配送方式transport """ # 获取到保存到session里面的用户id user_id = request.session.get('user_id') try: user = User.objects.get(pk=user_id) except: return JsonResponse({'error': 1, 'erg': '登录错误!'}) # 获取请求的数据 address_id = request.POST.get('address_id') transport_id = request.POST.get('transport') sku_id = request.POST.getlist('sku_id') # 判断请求的数据 if not all((address_id, transport_id, sku_id)): return JsonResponse({'error': 2, 'erg': '参数错误!'}) # 收货地址 try: address = ReceivingAddress.objects.filter( is_delete=0, user_id=user_id).get(pk=address_id) except: return JsonResponse({'error': 3, 'erg': '获取地址不纯在!'}) # 配送方式 try: transport = Hauling.objects.filter(is_delete=0).get( pk=transport_id) except: return JsonResponse({'error': 4, 'erg': '配送方式不纯在!'}) """ 添加订单数据 """ # 设置一个保存点,(事务回滚,回滚到该位置)以后回滚到该保存点位置 sid = transaction.savepoint() # 生成一个订单编号 order_sn = "{}{}{}".format(datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(1000, 9999), user_id) # 生成一个地址 order_address = '{}{}{}{}'.format(address.hcity, address.hproper, address.harea, address.detailed_description) print(order_address) print(order_sn) try: orderInfo = OrderInfo.objects.create( order_sn=order_sn, user=user, receiver=address.name, receiver_phone=address.phone, address=order_address, transport=transport, transport_price=transport.money, ) print(orderInfo) except: return JsonResponse({'error': 5, 'erg': '订单添加失败!'}) # 连接redis cnn = get_redis_connection("default") hset_id = 'car_%s' % user_id # 定义一个订单总价格 order_money = 0 # 获取商品信息 for skuid in sku_id: try: goods_sku = GoodsSkuInfo.objects.select_for_update().get( pk=skuid) # 加锁(解决高并发问题) except: # 手动回滚事务 transaction.savepoint_rollback(sid) return JsonResponse({"error": 6, "msg": "商品不存在!"}) # 获取购物车中商品的数量 count = cnn.hget(hset_id, skuid) print(count) count = int(count) # 判断库存是否足够 if goods_sku.goods_inventory < count: # 手动回滚事务 transaction.savepoint_rollback(sid) return JsonResponse({"error": 7, "msg": "商品库存不足!"}) # 保存订单商品表的数据 try: order_goods = OrderGoods.objects.create( order=orderInfo, goods_sku=goods_sku, price=goods_sku.goods_price, count=count) except: # 手动回滚事务 transaction.savepoint_rollback(sid) return JsonResponse({"error": 8, "msg": "创建订单商品数据失败!"}) # 订单商品表保存成功, 说明该商品的库存减少 goods_sku.goods_inventory -= count # 销量增加 goods_sku.goods_sales += count goods_sku.save() # 累计计算订单总价 order_money += count * goods_sku.goods_price # 将订单商品总价保存在订单基本信息表中 try: orderInfo.order_money = order_money orderInfo.save() except: # 手动回滚事务 transaction.savepoint_rollback(sid) return JsonResponse({"error": 9, "msg": "更新订单价格失败!"}) # 清空购物车 cnn.hdel(hset_id, *sku_id) # 提交事务 transaction.savepoint_commit(sid) return JsonResponse({ "error": 0, "msg": "创建订单成功", "order_sn": order_sn })
def post(self, request): user = request.user if not user.is_authenticated(): return JsonResponse({'res': -1, 'error': '用户未登录'}) addr_id = request.POST.get('addr_id') pay_method = request.POST.get('pay_method') sku_ids = request.POST.get('sku_ids') if not all([addr_id, pay_method, sku_ids]): return JsonResponse({'res': -2, 'error': '数据不完整'}) if pay_method not in OrderInfo.PAY_METHODS.keys(): return JsonResponse({'res': -3, 'error': '非法的支付方式'}) try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: return JsonResponse({'res': -4, 'error': '非法的地址'}) # 订单id格式:年月日时分秒+用户id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id) # 运费 transit_price = 10 # 总数目和总价 total_count = 0 total_price = 0 # 设置事务保存点 save_id = transaction.savepoint() try: # 向order_info表中添加一条记录 order = OrderInfo.objects.create(order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_count=total_count, total_price=total_price, transit_price=transit_price) # 用户的订单有几个商品,就需要在order_goods表中加入几条记录 conn = get_redis_connection('default') cart_key = 'cart_%d' % user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: # 乐观锁,尝试三次 for i in range(3): try: sku = GoodsSKU.objects.get(id=sku_id) # 加上悲观锁 等效SQL语句:select * from goods_sku where id=sku_id for update; # 当rollback或者commit后,自动释放锁 #sku = GoodsSKU.objects.select_for_update().get(id=sku_id) except: # 回滚到保存点 transaction.rollback(save_id) return JsonResponse({'res': -5, 'error': '商品不存在'}) # 从redis中获取用户所需要购买的商品数量 count = conn.hget(cart_key, sku_id) # 判断商品库存 if int(count) > sku.stock: # 回滚到保存点 transaction.rollback(save_id) return JsonResponse({'res': -6, 'error': '商品库存不足'}) # 更新商品库存和销量 # sku.stock -= int(count) # sku.sales += int(count) # sku.save() orign_stock = sku.stock new_stock = orign_stock - int(count) new_sales = sku.sales + int(count) # 乐观锁,等效SQL语句: # update goods_sku set stock=new_stock, sales=new_sales where id=sku_id and stock=origin_stock; # 返回受影响的行数 res = GoodsSKU.objects.filter( id=sku_id, stock=orign_stock).update(stock=new_stock, sales=new_sales) if res == 0: # 尝试到第三次还是失败的情况 if i == 2: transaction.savepoint_rollback(save_id) return JsonResponse({'res': -7, 'error': '下单失败'}) continue # order_goods表中加入记录 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # 累加计算订单商品总数和总价 amount = sku.price * int(count) total_count += int(count) total_price += amount break # 更新订单信息表中的商品总数和总价 order.total_count = total_count order.total_price = total_price order.save() except Exception: # 回滚到保存点 transaction.rollback(save_id) return JsonResponse({'res': -7, 'error': '下单失败'}) # 提交事务 transaction.savepoint_commit(save_id) # 清除用户购物车中对应记录 # *sku_ids: 将列表拆包 conn.hdel(cart_key, *sku_ids) return JsonResponse({'res': 1, 'msg': '创建成功'})
def obraCrear(request): form = None if request.method == 'POST': sid = transaction.savepoint() try: proceso = json.loads(request.POST.get('proceso')) print proceso print("en try") if 'clienProv' not in proceso: msg = 'El cliente no ha sido selecionado' raise Exception(msg) # if len(proceso['producto'])<=0: # msg = 'No se ha selecionado ningun producto' # raise Exception(msg) # if len(proceso['obrero']) <=0: # msg = 'No selecciono ningun obrero' # raise Exception(msg) #hasta aca era lo de obligatorio # for k in proceso['producto']: # print(k['codigo']) # producto = producto.objects.get(codigo=k['codigo']) crearObra = Obra( cliente=Cliente.objects.get(dni=proceso['clienProv']), fecha=timezone.now(), usuario=request.user, descripcion=proceso['descripcion'], direccion=proceso['direccion'], fechaInicio=proceso['fechaInicio'], fechaFinalizacion=proceso['fechaFinal'], porcentajeA=proceso['porcentajeA'], valorA=proceso['valorA'], porcentajeI=proceso['porcentajeI'], valorI=proceso['valorI'], porcentajeU=proceso['porcentajeU'], valorU=proceso['valorU'], formaPago=proceso['tipoPago'], iva=proceso['ivaU'], subtotal=proceso['subtotal'], total=proceso['total'], estado=proceso['estado'], ) crearObra.save() print "factura Guardada" print crearObra for k in proceso['producto']: producto = Producto.objects.get(codigo=k['codigo']) print(producto) crearDetalleProducto = DetalleObra( producto=producto, usuario=request.user, descripcion=producto.descripcion, cantidad=int(k['cantidad']), fecha=timezone.now(), obra=crearObra, ) crearDetalleProducto.save() print("Despues de crearDetalleProducto") for i in proceso['obrero']: obrero = Obrero.objects.get(dni=i['dni']) print(obrero) crearDetalleObrero = DetalleObreroObra( obra=crearObra, obrero=obrero, usuario=request.user, ) crearDetalleObrero.save() messages.success(request, 'La venta se ha realizado') except Exception, e: try: transaction.savepoint_rollback(sid) except: pass messages.error(request, e)
def create(self, validated_data): """ 保存订单 """ # 获取当前下单用户 user = self.context['request'].user # 组织订单编号 20170903153611+user.id # timezone.now() -> datetime order_id = timezone.now().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id) address = validated_data['address'] pay_method = validated_data['pay_method'] # 生成订单 with transaction.atomic(): # 创建一个保存点 save_id = transaction.savepoint() try: # 创建订单信息 order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=0, total_amount=Decimal(0), freight=Decimal(10), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNSEND'] if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH'] else OrderInfo.ORDER_STATUS_ENUM['UNPAID']) # 获取购物车信息 redis_conn = get_redis_connection("cart") redis_cart = redis_conn.hgetall("cart_%s" % user.id) cart_selected = redis_conn.smembers('cart_selected_%s' % user.id) # 将bytes类型转换为int类型 cart = {} for sku_id in cart_selected: cart[int(sku_id)] = int(redis_cart[sku_id]) # # 一次查询出所有商品数据 # skus = SKU.objects.filter(id__in=cart.keys()) # 处理订单商品 sku_id_list = cart.keys() for sku_id in sku_id_list: while True: sku = SKU.objects.get(id=sku_id) sku_count = cart[sku.id] # 判断库存 origin_stock = sku.stock # 原始库存 origin_sales = sku.sales # 原始销量 if sku_count > origin_stock: transaction.savepoint_rollback(save_id) raise serializers.ValidationError('商品库存不足') # 用于演示并发下单 # import time # time.sleep(5) # 减少库存 # sku.stock -= sku_count # sku.sales += sku_count # sku.save() new_stock = origin_stock - sku_count new_sales = origin_sales + sku_count # 根据原始库存条件更新,返回更新的条目数,乐观锁 ret = SKU.objects.filter(id=sku.id, stock=origin_stock).update( stock=new_stock, sales=new_sales) if ret == 0: continue # 累计商品的SPU 销量信息 sku.goods.sales += sku_count sku.goods.save() # 累计订单基本信息的数据 order.total_count += sku_count # 累计总金额 order.total_amount += (sku.price * sku_count) # 累计总额 # 保存订单商品 OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 更新成功 break # 更新订单的金额数量信息 order.total_amount += order.freight order.save() except serializers.ValidationError: raise except Exception as e: # logger.error(e) transaction.savepoint_rollback(save_id) raise # 提交事务 transaction.savepoint_commit(save_id) # 更新redis中保存的购物车数据 pl = redis_conn.pipeline() pl.hdel('cart_%s' % user.id, *cart_selected) pl.srem('cart_selected_%s' % user.id, *cart_selected) pl.execute() return order
def post(self, request): """保存订单信息和订单商品信息""" json_dict = json.loads(request.body.decode()) address_id = json_dict.get('address_id') pay_method = json_dict.get('pay_method') # 校验参数 if not all([address_id, pay_method]): return http.HttpResponseForbidden('缺少必传参数') # 判断address_id是否合法 try: address = Address.objects.get(id=address_id) except Exception: return http.HttpResponseForbidden('参数address_id错误') # 判断pay_method是否合法 if pay_method not in [ OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY'] ]: return http.HttpResponseForbidden('参数pay_method错误') # 获取登录用户 user = request.user # 生成订单编号:年月日时分秒+用户编号 order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id) # 显式的开启一个事务 with transaction.atomic(): # 创建事务保存点 save_id = transaction.savepoint() # 保存订单基本信息 OrderInfo(一) order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=0, total_amount=Decimal('0'), freight=Decimal('10.00'), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND']) # 从redis读取购物车中被勾选的商品信息 redis_conn = get_redis_connection('carts') redis_cart = redis_conn.hgetall('carts_%s' % user.id) selected = redis_conn.smembers('selected_%s' % user.id) carts = {} for sku_id in selected: carts[int(sku_id)] = int(redis_cart[sku_id]) sku_ids = carts.keys() # 遍历购物车中被勾选的商品信息 for sku_id in sku_ids: # 查询SKU信息 # 增加的代码: 增加一个死循环 while True: # 查询SKU信息 sku = SKU.objects.get(id=sku_id) # 增加的代码: 读取原始库存 origin_stock = sku.stock origin_sales = sku.sales # 判断SKU库存 sku_count = carts[sku.id] if sku_count > sku.stock: # 事务回滚 transaction.savepoint_rollback(save_id) return http.JsonResponse({ 'code': 400, 'errmsg': '库存不足' }) # 模拟延迟 # import time # time.sleep(5) # SKU减少库存,增加销量 # sku.stock -= sku_count # sku.sales += sku_count # sku.save() # 增加的代码: 乐观锁更新库存和销量 # 计算差值 new_stock = origin_stock - sku_count new_sales = origin_sales + sku_count result = SKU.objects.filter( id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales) # 如果下单失败,但是库存足够时, # 继续下单,直到下单成功或者库存不足为止 if result == 0: continue # 修改SPU销量 sku.goods.sales += sku_count sku.goods.save() # 保存订单商品信息 OrderGoods(多) OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 保存商品订单中总价和总数量 order.total_count += sku_count order.total_amount += (sku_count * sku.price) # 增加的代码: # 下单成功或者失败就跳出循环 break # 添加邮费和保存订单信息 order.total_amount += order.freight order.save() # 清除保存点 transaction.savepoint_commit(save_id) # 清除购物车中已结算的商品 pl = redis_conn.pipeline() pl.hdel('carts_%s' % user.id, *selected) pl.srem('selected_%s' % user.id, *selected) pl.execute() # 响应提交订单结果 return http.JsonResponse({ 'code': 0, 'errmsg': '下单成功', 'order_id': order.order_id })
def save_data(self, project, data, raw=False): # TODO: this function is way too damn long and needs refactored # the inner imports also suck so let's try to move it away from # the objects manager # TODO: culprit should default to "most recent" frame in stacktraces when # it's not provided. from sentry.plugins import plugins from sentry.models import Event, Project, EventMapping project = Project.objects.get_from_cache(id=project) # First we pull out our top-level (non-data attr) kwargs event_id = data.pop('event_id') message = data.pop('message') culprit = data.pop('culprit') or '' level = data.pop('level') time_spent = data.pop('time_spent') logger_name = data.pop('logger') server_name = data.pop('server_name') site = data.pop('site') date = data.pop('timestamp') checksum = data.pop('checksum') platform = data.pop('platform') kwargs = { 'message': message, 'platform': platform, } event = Event(project=project, event_id=event_id, data=data, time_spent=time_spent, datetime=date, **kwargs) # Calculate the checksum from the first highest scoring interface if not checksum: checksum = get_checksum_from_event(event) event.checksum = checksum group_kwargs = kwargs.copy() group_kwargs.update({ 'culprit': culprit, 'logger': logger_name, 'level': level, 'last_seen': date, 'first_seen': date, 'time_spent_total': time_spent or 0, 'time_spent_count': time_spent and 1 or 0, }) tags = data['tags'] tags.append(('level', LOG_LEVELS[level])) if logger: tags.append(('logger', logger_name)) if server_name: tags.append(('server_name', server_name)) if site: tags.append(('site', site)) for plugin in plugins.for_project(project): added_tags = safe_execute(plugin.get_tags, event) if added_tags: tags.extend(added_tags) try: group, is_new, is_regression, is_sample = self._create_group( event=event, tags=data['tags'], **group_kwargs) except Exception as exc: # TODO: should we mail admins when there are failures? try: logger.exception(u'Unable to process log entry: %s', exc) except Exception as exc: warnings.warn(u'Unable to process log entry: %s', exc) return using = group._state.db event.group = group # save the event unless its been sampled if not is_sample: sid = transaction.savepoint(using=using) try: event.save() except IntegrityError: transaction.savepoint_rollback(sid, using=using) return event transaction.savepoint_commit(sid, using=using) sid = transaction.savepoint(using=using) try: EventMapping.objects.create(project=project, group=group, event_id=event_id) except IntegrityError: transaction.savepoint_rollback(sid, using=using) return event transaction.savepoint_commit(sid, using=using) transaction.commit_unless_managed(using=using) if not raw: send_group_processors( group=group, event=event, is_new=is_new or is_regression, # backwards compat is_sample=is_sample, is_regression=is_regression, ) index_event.delay(event) # TODO: move this to the queue if is_new and not raw: regression_signal.send_robust(sender=self.model, instance=group) return event
def post(self,request): """保持订单信息""" data=json.loads(request.body.decode()) address_id=data.get('address_id') pay_method=data.get('pay_method') #数据校验 if not all([address_id,pay_method]): return JsonResponse({ 'code':400, 'errmsg':'缺少必要参数' }) try: address=Address.objects.get(pk=address_id) except Exception as e: return ({ 'code':400, 'errmsg':'地址错误' }) if pay_method not in [1,2]: return JsonResponse({ 'code':400, 'errmsg':'不支持的付款方式' }) user=request.user order_id=timezone.localtime().strftime("%Y%m%d%H%M%S")+"%09d"%user.id #保存顶单信息 with transaction.atomic(): save_id=transaction.savepoint()#事务执行保存点 order=OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_count=0, total_amount=Decimal('0'), freight=Decimal('10.00'), pay_method=pay_method, status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method==OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND'] ) #读取购物车被勾选商品 redis_conn=get_redis_connection("carts") cart_dict=redis_conn.hgetall('carts_%s'%user.id) selected_redis=redis_conn.smembers('selected_%s'%user.id) carts={} for k,v in cart_dict.items(): if k in selected_redis: carts[int(k)] = int(v) #获取商品id sku_ids=carts.keys() #便利查询商品信息 for sku_id in sku_ids: while True: sku=SKU.objects.get(id=sku_id) old_stock=sku.stock old_sales=sku.sales #判断库存 sku_count=carts[sku.id] if sku_count > sku.stock: transaction.savepoint_rollback(save_id) #回滚 return JsonResponse({ 'code':400, 'errmsg':'库存不足' }) #修改数据库 # sku.stock-=sku_count # sku.sales+=sku_count # sku.save() new_stock=old_stock-sku_count new_sales=old_sales+sku_count result=SKU.objects.filter(id=sku.id, stock=old_stock, sales=old_sales).update( stock=new_stock,sales=old_sales ) if result==0: continue break #修改spu销量 # sku.goods.sales+=sku_count # sku.goods.save() #保存订单商品信息 OrderGoods.objects.create( order=order, sku=sku, count=carts[sku_id], price=sku.price ) order.total_count+=sku_count order.total_amount+=(sku_count*sku.price) order.total_amount+=order.freight order.save() transaction.savepoint_commit(save_id) #清楚购物车结算商品 redis_conn.hdel('carts_%s'%user.id,*selected_redis) redis_conn.srem('selected_%s'%user.id,*selected_redis) #返回响应 return JsonResponse({ 'code':0, 'errmsg':'下单成功', 'order_id':order.order_id })
def import_data_inner(self, dataset, dry_run, raise_errors, using_transactions, collect_failed_rows, **kwargs): result = self.get_result_class()() result.diff_headers = self.get_diff_headers() result.total_rows = len(dataset) if using_transactions: # when transactions are used we want to create/update/delete object # as transaction will be rolled back if dry_run is set sp1 = savepoint() try: self.before_import(dataset, using_transactions, dry_run, **kwargs) except Exception as e: logging.exception(e) tb_info = traceback.format_exc() result.append_base_error(self.get_error_result_class()(e, tb_info)) if raise_errors: if using_transactions: savepoint_rollback(sp1) raise instance_loader = self._meta.instance_loader_class(self, dataset) # Update the total in case the dataset was altered by before_import() result.total_rows = len(dataset) if collect_failed_rows: result.add_dataset_headers(dataset.headers) for row in dataset.dict: row_result = self.import_row(row, instance_loader, using_transactions=using_transactions, dry_run=dry_run, **kwargs) result.increment_row_result_total(row_result) if row_result.errors: if collect_failed_rows: result.append_failed_row(row, row_result.errors[0]) if raise_errors: if using_transactions: savepoint_rollback(sp1) raise row_result.errors[-1].error if (row_result.import_type != RowResult.IMPORT_TYPE_SKIP or self._meta.report_skipped): result.append_row_result(row_result) try: self.after_import(dataset, result, using_transactions, dry_run, **kwargs) except Exception as e: logging.exception(e) tb_info = traceback.format_exc() result.append_base_error(self.get_error_result_class()(e, tb_info)) if raise_errors: if using_transactions: savepoint_rollback(sp1) raise if using_transactions: if dry_run or result.has_errors(): savepoint_rollback(sp1) else: savepoint_commit(sp1) return result
def put(self, request, *args, **kwargs): """ 修改构建源 --- """ s_id = transaction.savepoint() try: image = request.data.get("image", None) cmd = request.data.get("cmd", None) service_source = request.data.get("service_source") git_url = request.data.get("git_url", None) code_version = request.data.get("code_version", None) user_name = request.data.get("user_name", None) password = request.data.get("password", None) is_oauth = request.data.get("is_oauth", False) user_id = request.user.user_id oauth_service_id = request.data.get("service_id") git_full_name = request.data.get("full_name") if not service_source: return Response(general_message(400, "param error", "参数错误"), status=400) service_source_user = service_source_repo.get_service_source( team_id=self.service.tenant_id, service_id=self.service.service_id) if not service_source_user: service_source_info = { "service_id": self.service.service_id, "team_id": self.service.tenant_id, "user_name": user_name, "password": password, "create_time": datetime.datetime.now().strftime('%Y%m%d%H%M%S') } service_source_repo.create_service_source(**service_source_info) else: service_source_user.user_name = user_name service_source_user.password = password service_source_user.save() if service_source == "source_code": if code_version: self.service.code_version = code_version else: self.service.code_version = "master" if git_url: if is_oauth: try: oauth_service = oauth_repo.get_oauth_services_by_service_id(service_id=oauth_service_id) oauth_user = oauth_user_repo.get_user_oauth_by_user_id(service_id=oauth_service_id, user_id=user_id) except Exception as e: logger.debug(e) rst = {"data": {"bean": None}, "status": 400, "msg_show": u"未找到OAuth服务, 请检查该服务是否存在且属于开启状态"} return Response(rst, status=200) try: instance = get_oauth_instance(oauth_service.oauth_type, oauth_service, oauth_user) except Exception as e: logger.debug(e) rst = {"data": {"bean": None}, "status": 400, "msg_show": u"未找到OAuth服务"} return Response(rst, status=200) if not instance.is_git_oauth(): rst = {"data": {"bean": None}, "status": 400, "msg_show": u"该OAuth服务不是代码仓库类型"} return Response(rst, status=200) service_code_from = "oauth_" + oauth_service.oauth_type self.service.code_from = service_code_from self.service.git_url = git_url self.service.git_full_name = git_full_name self.service.oauth_service_id = oauth_service_id self.service.creater = user_id else: self.service.git_url = git_url self.service.save() transaction.savepoint_commit(s_id) elif service_source == "docker_run": if image: version = image.split(':')[-1] if not version: version = "latest" image = image + ":" + version self.service.image = image self.service.version = version self.service.cmd = cmd self.service.save() transaction.savepoint_commit(s_id) result = general_message(200, "success", "修改成功") except Exception as e: logger.exception(e) result = error_message(e.message) transaction.savepoint_rollback(s_id) return Response(result, status=result["code"])
def post(self, request): # 获取参数 # user 地址id 支付方式 商品id 数量(从购物车中获取) user = request.user address_id = request.POST.get("address_id") sku_ids = request.POST.get("sku_ids") # "1,2,3,4" pay_method = request.POST.get("pay_method") # 校验参数 if not all([address_id, sku_ids, pay_method]): return JsonResponse({"code": 2, "message": "参数缺失"}) # 判断地址是否存在 try: address = Address.objects.get(id=address_id) except Address.DoesNotExist: return JsonResponse({"code": 3, "message": "地址不存在"}) # 判断支付方式 pay_method = int(pay_method) if pay_method not in OrderInfo.PAY_METHODS.keys(): return JsonResponse({"code": 4, "message": "支付方式错误"}) # 判断商品 sku_ids = sku_ids.split(",") # ["1", "2"] redis_conn = get_redis_connection("default") cart = redis_conn.hgetall("cart_%s" % user.id) # 创建一个订单基本信息表数据 # 自定义的order_id "20171026111111用户id" order_id = timezone.now().strftime("%Y%m%d%H%M%S") + str(user.id) # 创建事务保存点 save_id = transaction.savepoint() try: order = OrderInfo.objects.create( order_id=order_id, user=user, address=address, total_amount=0, trans_cost=10, pay_method=pay_method, ) total_count = 0 # 总数 total_amount = 0 # 总金额 for sku_id in sku_ids: for i in range(3): try: sku = GoodsSKU.objects.get(id=sku_id) except GoodsSKU.DoesNotExist: # 回退的保存点的状态 transaction.savepoint_rollback(save_id) return JsonResponse({"code": 5, "message": "商品有误"}) # 获取订购的商品数量,判断库存 sku_count = cart.get(sku_id.encode()) sku_count = int(sku_count) if sku_count > sku.stock: # 回退的保存点的状态 transaction.savepoint_rollback(save_id) return JsonResponse({"code": 6, "message": "库存不足"}) # 减少商品的库存, 增加商品的销量 origin_stock = sku.stock new_stock = origin_stock - sku_count new_sales = sku.sales + sku_count # update操作会返回受影响的行数,即更新成功的函数 result = GoodsSKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock, sales=new_sales) if result == 0 and i < 2: # 表示更新失败 continue elif result == 0 and i == 2: # 表示尝试三次失败 transaction.savepoint_rollback(save_id) return JsonResponse({"code": 7, "message": "下单失败"}) # 保存订单商品 OrderGoods.objects.create( order=order, sku=sku, count=sku_count, price=sku.price, ) # 累计计算总数 total_count += sku_count # 累计计算总金额 total_amount += (sku.price * sku_count) # 跳出三次循环,处理下一个商品 break # 修改订单基本信息表中的统计数据字段 order.total_count = total_count order.total_amount = total_amount + 10 order.save() except Exception: # 出现任何异常,都要回退的保存点的状态 transaction.savepoint_rollback(save_id) return JsonResponse({"code": 8, "message": "下单失败"}) # 执行成功,提交事务 transaction.savepoint_commit(save_id) # 保存最新的购物车数据 redis_conn.hdel("cart_%s" % user.id, *sku_ids) # 删除订购的商品 # 返回前端json状态 return JsonResponse({"code": 0, "message": "创建订单成功"})
def post(self, request): user = request.user if not user.is_authenticated: return JsonResponse({'res': 0, 'errmsg': 'Please login first'}) addr_id = request.POST.get('addr_id') pay_method = int(request.POST.get('pay_method')) sku_ids = request.POST.get('sku_ids') # sku_ids = 1,3,5,16.... if not all([addr_id, pay_method, sku_ids]): return JsonResponse({ 'res': 1, 'errmsg': 'Address fields is incomplete' }) if pay_method not in OrderInfo.PAYMENT_METHODS.keys(): return JsonResponse({'res': 2, 'errmsg': 'Invalid payment method'}) try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: return JsonResponse({'res': 3, 'errmsg': 'Invalid address'}) # Implement create order service # Create order_info 1st, then order_goods because there's order_info_id foreign key in order_goods # Ex: order_id = 20190722160830+user.id order_id = datetime.now().strftime('%Y%m%d%H%M%S') + str(user.id) # goods total_count & total price total_count = 0 total_price = 0 # Setup savepoints save_id = transaction.savepoint() try: order = OrderInfo.objects.create( order_id=order_id, user=user, addr=addr, payment_method=pay_method, goods_total_count=total_count, goods_total_price=total_price, ) # For any sku items in user's cart, # we need to create each sku order_gooods model & record it conn = get_redis_connection('default') cart_key = 'cart_{user_id}'.format(user_id=user.id) sku_ids = sku_ids.split(',') for sku_id in sku_ids: try: # MySQL syntax: select * from sf_goods_sku where id=sku_id for update; sku = GoodsSKU.objects.select_for_update().get(id=sku_id) except: transaction.savepoint_rollback(save_id) return JsonResponse({ 'res': 4, 'errmsg': 'SKU id does not exists' }) count = conn.hget(cart_key, sku_id) count = int(count) # Verify whether intend to purchase item's sku quantity exceed item's sku stock or not, # if it is rollback to save point if count > sku.stock: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 5, 'errmsg': 'Out of stock'}) OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # Update GoodsSKU stock & sales sku.stock -= count sku.sales += count sku.save() # Update / accumulate order item's count and amount to total_count & total_price amount = sku.price * count total_count += count total_price += amount order.goods_total_count = total_count order.goods_total_price = total_price order.save() except Exception as e: transaction.savepoint_rollback(save_id) return JsonResponse({ 'res': 6, 'errmsg': 'You already added this order in your order page' }) # After purchased all the selected goods from cart, we need to remove these goods' # sku id from Redis with key = cart_user.id transaction.savepoint_commit(save_id) conn.hdel(cart_key, *sku_ids) return JsonResponse({'res': 7, 'message': 'Checkout successfully!'})
def post(self, request): # 获取登录的用户 user = request.user # 判断用户是否登录 if not user.is_authenticated(): # 未登录 return JsonResponse({'res': 0, 'errmsg': '请先登录'}) # 接收参数 sku_ids = request.POST.get('sku_ids') addr_id = request.POST.get('addr_id') pay_method = request.POST.get('pay_method') print(pay_method) # 校验参数 if not all([sku_ids, addr_id, pay_method]): return JsonResponse({'res': 1, 'errmsg': '数据不完整'}) # 校验支付方式是否存在 if pay_method not in OrderInfo.PAY_METHODS.keys(): # 非法支付方式 return JsonResponse({'res': 2, 'errmsg': '非法支付方式'}) # 判断地址是否存在 try: addr = Address.objects.get(id=addr_id) except Address.DoesNotExist: return JsonResponse({'res': 3, 'errmsg': '地址不存在'}) # 业务处理: 订单创建 # 组织参数 # 订单id: 时间 + user.id == 202001081010+user.id order_id = datetime.now().strftime("%Y%m%d%H%M%S") + str(user.id) # 运费 transit_price = 10 # 总数目和总价格 total_count = 0 total_price = 0 # 设置保存点 save_id = transaction.savepoint() try: # 向p1_order_info中添加一条信息 order = OrderInfo.objects.create(order_id=order_id, user=user, addr=addr, pay_method=pay_method, total_price=total_price, total_count=total_count, transit_price=transit_price) # 订单中有几个商品需要向订单商品表中添加几条信息: p1_order_goods conn = get_redis_connection('default') cart_key = 'cart_%d'%user.id sku_ids = sku_ids.split(',') for sku_id in sku_ids: # 获取商品不存在 try: # 悲观锁 高并发 sku = GoodsSKU.objects.select_for_update().get(id=sku_id) except GoodsSKU.DoesNotExist: # 商品不存在 # 事务回滚save_id transaction.savepoint_rollback(save_id) return JsonResponse({'res': 4, 'errmsg': '商品不存在'}) # 测试悲观锁 print("user_id: %d, stock: %d" %(user.id, sku.stock)) import time time.sleep(10) # 从redis中获取用户购买商品的数量 count = conn.hget(cart_key, sku_id) # 判断商品的库存 if int(count) > sku.stock: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 6, 'errmsg': '商品库存不足'}) # 向表中添加一条数据 OrderGoods.objects.create(order=order, sku=sku, count=count, price=sku.price) # 更新商品的库存和销量 sku.stock -= int(count) sku.sales += int(count) sku.save() # 累加计算商品的总数量和总价格 amount = sku.price * int(count) total_count += int(count) total_price += amount # 更新订单信息表中的总数量和总价格 order.total_count = total_count order.total_price = total_price order.save() except Exception as e: transaction.savepoint_rollback(save_id) return JsonResponse({'res': 7, 'errmsg': '下单失败'}) # 业务提交 transaction.savepoint_commit(save_id) # 清除用户购物车记录 conn.hdel(cart_key, *sku_ids) # 返回应答 return JsonResponse({'res': 5, 'message': '创建成功'})
def addon_view_or_download_file(auth, path, provider, **kwargs): extras = request.args.to_dict() extras.pop('_', None) # Clean up our url params a bit action = extras.get('action', 'view') node = kwargs.get('node') or kwargs['project'] node_addon = node.get_addon(provider) provider_safe = markupsafe.escape(provider) path_safe = markupsafe.escape(path) project_safe = markupsafe.escape(node.project_or_component) if not path: raise HTTPError(httplib.BAD_REQUEST) if not isinstance(node_addon, BaseStorageAddon): raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer connected to {}.'.format(provider_safe, path_safe, project_safe) }) if not node_addon.has_auth: raise HTTPError(httplib.UNAUTHORIZED, data={ 'message_short': 'Unauthorized', 'message_long': 'The {} add-on containing {} is no longer authorized.'.format(provider_safe, path_safe) }) if not node_addon.complete: raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'The {} add-on containing {} is no longer configured.'.format(provider_safe, path_safe) }) savepoint_id = transaction.savepoint() file_node = BaseFileNode.resolve_class(provider, BaseFileNode.FILE).get_or_create(node, path) # Note: Cookie is provided for authentication to waterbutler # it is overriden to force authentication as the current user # the auth header is also pass to support basic auth version = file_node.touch( request.headers.get('Authorization'), **dict( extras, cookie=request.cookies.get(settings.COOKIE_NAME) ) ) if version is None: # File is either deleted or unable to be found in the provider location # Rollback the insertion of the file_node transaction.savepoint_rollback(savepoint_id) if not file_node.pk: file_node = BaseFileNode.load(path) # Allow osfstorage to redirect if the deep url can be used to find a valid file_node if file_node and file_node.provider == 'osfstorage' and not file_node.is_deleted: return redirect( file_node.node.web_url_for('addon_view_or_download_file', path=file_node._id, provider=file_node.provider) ) return addon_deleted_file(file_node=file_node, path=path, **kwargs) else: transaction.savepoint_commit(savepoint_id) # TODO clean up these urls and unify what is used as a version identifier if request.method == 'HEAD': return make_response(('', httplib.FOUND, { 'Location': file_node.generate_waterbutler_url(**dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render')) })) if action == 'download': format = extras.get('format') _, extension = os.path.splitext(file_node.name) # avoid rendering files with the same format type. if format and '.{}'.format(format.lower()) != extension.lower(): return redirect('{}/export?format={}&url={}'.format(MFR_SERVER_URL, format, urllib.quote(file_node.generate_waterbutler_url( **dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render') )))) return redirect(file_node.generate_waterbutler_url(**dict(extras, direct=None, version=version.identifier, _internal=extras.get('mode') == 'render'))) if action == 'get_guid': draft_id = extras.get('draft') draft = DraftRegistration.load(draft_id) if draft is None or draft.is_approved: raise HTTPError(httplib.BAD_REQUEST, data={ 'message_short': 'Bad Request', 'message_long': 'File not associated with required object.' }) guid = file_node.get_guid(create=True) guid.referent.save() return dict(guid=guid._id) if len(request.path.strip('/').split('/')) > 1: guid = file_node.get_guid(create=True) return redirect(furl.furl('/{}/'.format(guid._id)).set(args=extras).url) return addon_view_file(auth, node, file_node, version)
def facturaCrear(request): form = None if request.method == 'POST': sid = transaction.savepoint() try: proceso = json.loads(request.POST.get('proceso')) print proceso if 'serie' not in proceso: msg = 'Ingrese Serie' raise Exception(msg) if 'numero' not in proceso: msg = 'Ingrese Numero' raise Exception(msg) if 'clienProv' not in proceso: msg = 'No ha seleccionado al cliente' raise Exception(msg) if len(proceso['producto']) <= 0: msg = 'No ha seleccionado ningun producto' raise Exception(msg) total = 0 for k in proceso['producto']: producto = Medicamentos.objects.get(id=k['serial']) subTotal = (producto.precio_venta) * int(k['cantidad']) total += subTotal crearFactura = Factura( serie=proceso['serie'], numero=proceso['numero'], cliente=Cliente.objects.get(id=proceso['clienProv']), fecha=timezone.now(), total=total, vendedor=request.user ) crearFactura.save() print "Factura guardada" print crearFactura.id for k in proceso['producto']: producto = Medicamentos.objects.get(id=k['serial']) crearDetalle = DetalleFactura( producto=producto, descripcion=producto.nombre, precio = producto.precio_venta, cantidad=int(k['cantidad']), impuesto=producto.igv* int(k['cantidad']), subtotal=producto.precio_venta * int(k['cantidad']), factura = crearFactura, ) crearDetalle.save() messages.success( request, 'La venta se ha realizado correctamente') except Exception, e: try: transaction.savepoint_rollback(sid) except: pass messages.error(request, e)