Esempio n. 1
0
    def update_slot(cls,
                    exam_reg_pk,
                    exam_slot_pk,
                    request_time=None,
                    force=False):

        warnings = set()

        # Check some basic facts
        if True:
            exam_reg = ExamRegistration.objects.get(pk=exam_reg_pk)

            # Enforce lock_before and lock_after
            exam = exam_reg.exam
            if request_time is not None:
                if (exam.lock_before is not None
                        and request_time < exam.lock_before):
                    warnings.add("Exam registration is not yet open")

                if (exam.lock_after is not None
                        and request_time >= exam.lock_after):
                    warnings.add("Exam registration has closed")

            # Don't allow dropped users to change.
            if exam_reg.course_user.dropped:
                warnings.add("You have dropped the course")

        # Begin atomic section
        if not warnings or force:
            with transaction.atomic():
                exam_reg = ExamRegistration.objects.get(pk=exam_reg_pk)

                # Don't allow checked-in users to change.
                if exam_reg.checkin_time:
                    warnings.add(
                        "You have already been checked in for this exam")

                # Clear exam slot (in transaction)
                # This is so when counting registered in time slots below,
                # we don't include ourselves in the count
                if exam_reg.exam_slot is not None:
                    old_exam_slot = exam_reg.exam_slot
                    old_exam_slot.reg_count -= 1
                    old_exam_slot.save(update_fields=['reg_count'])

                # Try to update the slot
                if exam_slot_pk is not None:

                    # Get new exam slot, time slot list
                    exam_slot = ExamSlot.objects \
                            .select_for_update() \
                            .get(pk=exam_slot_pk)

                    # Check that exam slot type is correct
                    if (exam_slot.exam_slot_type !=
                            exam_reg.course_user.exam_slot_type):
                        warnings.add("Wrong exam slot type")

                    # Check that all time slots have seats
                    for time_slot in exam_slot.time_slots.all():
                        if (time_slot.count_num_registered() >=
                                time_slot.capacity):
                            warnings.add("Not enough seats left")

                    # Update the exam registration
                    exam_slot.reg_count += 1
                    exam_slot.save(update_fields=['reg_count'])

                    exam_reg.exam_slot = exam_slot
                    exam_reg.save(update_fields=['exam_slot'])

                else:
                    exam_reg.exam_slot = None
                    exam_reg.save(update_fields=['exam_slot'])

                if warnings and not force:
                    raise IntegrityError('; '.join(warnings))

        return warnings
Esempio n. 2
0
 def save(self, *args, **kwargs):
     """don't create a request for a registered email"""
     if not self.id and User.objects.filter(email=self.email).exists():
         raise IntegrityError()
     super().save(*args, **kwargs)
Esempio n. 3
0
def get_current_term():
    current_terms = CurrentTerm.objects.all()
    if current_terms.count() != 1:
        raise IntegrityError('There must be exactly 1 current term object')
    return current_terms[0].current_term
Esempio n. 4
0
    def create(self, validated_data):
        """
        This function exists becuase it's the only function this serializer
        is allowed to do, AND we've got some caveats about doing it. Mainly verifying
        that it's a valid word etc.

        Basically, we go through and try to do everything. If there's an error, it will
        mostly be a DoesNotExist, and mostly we want to throw that back for the frontend to
        deal with.
        """
        errormessage = ""

        # puzzleplay is the universal play object, with player=None
        puzzleplay = validated_data['puzzle']

        # play is THIS USER'S play object. We'll need this to check what rules this user is
        # playing by.
        try:
            try:
                play = models.Play.objects.filter(puzzle=puzzleplay.puzzle,
                                                  player=self.context['request'].user.player)[0]
            except AttributeError:
                raise PermissionDenied
        except IndexError:
            # There is no play record for this user/puzzle combination. Create it.
            play = models.Play(puzzle=puzzleplay.puzzle, player=self.context['request'].user.player)
            play.save()

        try:
            # Here, we get the correct word record for this word. But note the roundabout method
            # This is to make sure that it exists FOR THIS PUZZLE. Simply finding it isn't enough.
            word = models.WordList.objects.filter(
                play=puzzleplay,
                word__word=validated_data['word']
            )[0].word
        except IndexError:
            errormessage = "invalid word. Not on this puzzle or not a word."
            if play.missed:
                # Track missed words by adding a wordlist record with no word.
                word = None
            else:
                raise IntegrityError(errormessage)

        # Create the wordlist object.
        wordlist = models.WordList(word=word, play=play, foundtime=validated_data['foundtime'])

        try:
            wordlist.save()
        except IntegrityError:
            errormessage = "Not Unique. Word alread found."
            # The user entered the same word again.
            if play.repeats:
                # Track repeated words by adding a wordlist record with no word.
                wordlist.word = None
                # This "save" call should never get a uniqueness check failed, because null!=null
                # (according to SQL)
                wordlist.save()
            else:
                raise IntegrityError(errormessage)

        # Lie about it: If word=null, raise an integrityError
        if(wordlist.word is None):
            raise IntegrityError(errormessage)

        return wordlist
Esempio n. 5
0
File: models.py Progetto: misli/iq
 def save(self, *args, **kwargs):
     if self.subject.scheme == self.level.scheme:
         return super(Teach, self).save(*args, **kwargs)
     else:
         raise IntegrityError("schemes didn't match")
Esempio n. 6
0
 def raise_exception():
     raise IntegrityError()
Esempio n. 7
0
 def integrity_error_side_effect(username="******"):
     raise IntegrityError()
Esempio n. 8
0
def periodic_pay_pre_delete(sender, **kwargs):
    raise IntegrityError('All linked abonapp.PeriodicPayForId will be removed, be careful')
 def save(self, *args, **kwargs):
     if self.id is None:
         super(Transactions, self).save(*args, **kwargs)
     else:
         raise IntegrityError('This model instance cannot be updated')
Esempio n. 10
0
def save_model_checks(sender, instance, using, **kwargs):
    if instance.files.filter(kind=ModelFile.MAIN).count() > 1:
        raise IntegrityError("You can only have one main model file!")
Esempio n. 11
0
 def ca_weirdness(**data):
     ca_doc = Document()
     for name, value in data.items():
         setattr(ca_doc, name, value)
     ca_doc.save()
     raise IntegrityError('ID in use')
Esempio n. 12
0
def create_uploaded_persons_tasks(data, request=None):
    """
    Create persons and tasks from upload data.
    """

    # Quick sanity check.
    if any([row.get("errors") for row in data]):
        raise InternalError("Uploaded data contains errors, cancelling upload")

    persons_created = []
    tasks_created = []
    events = set()

    with transaction.atomic():
        for row in data:
            try:
                row_repr = ("{personal} {family} {username} <{email}>, "
                            "{role} at {event}").format(**row)

                fields = {key: row[key] for key in Person.PERSON_UPLOAD_FIELDS}
                fields["username"] = row["username"]

                if row["person_exists"] and row["existing_person_id"]:
                    # we should use existing Person
                    p = Person.objects.get(pk=row["existing_person_id"])

                elif row["person_exists"] and not row["existing_person_id"]:
                    # we should use existing Person
                    p = Person.objects.get(
                        personal=fields["personal"],
                        family=fields["family"],
                        username=fields["username"],
                        email=fields["email"],
                    )

                else:
                    # we should create a new Person without any email provided
                    p = Person(**fields)
                    p.save()
                    persons_created.append(p)

                if row["event"] and row["role"]:
                    e = Event.objects.get(slug=row["event"])
                    r = Role.objects.get(name=row["role"])

                    # if the number of learners attending the event changed,
                    # we should update ``event.attendance``
                    if row["role"] == "learner":
                        events.add(e)

                    t, created = Task.objects.get_or_create(person=p,
                                                            event=e,
                                                            role=r)
                    if created:
                        tasks_created.append(t)

            except IntegrityError as e:
                raise IntegrityError('{0} (for "{1}")'.format(
                    str(e), row_repr))

            except ObjectDoesNotExist as e:
                raise ObjectDoesNotExist('{0} (for "{1}")'.format(
                    str(e), row_repr))

    jobs_created = []
    rqjobs_created = []

    # for each created task, try to add a new-(supporting)-instructor action
    with transaction.atomic():
        for task in tasks_created:
            # conditions check out
            if NewInstructorAction.check(task):
                objs = dict(task=task, event=task.event)
                # prepare context and everything and create corresponding RQJob
                jobs, rqjobs = ActionManageMixin.add(
                    action_class=NewInstructorAction,
                    logger=logger,
                    scheduler=scheduler,
                    triggers=Trigger.objects.filter(active=True,
                                                    action="new-instructor"),
                    context_objects=objs,
                    object_=task,
                    request=request,
                )
                jobs_created += jobs
                rqjobs_created += rqjobs

            # conditions check out
            if NewSupportingInstructorAction.check(task):
                objs = dict(task=task, event=task.event)
                # prepare context and everything and create corresponding RQJob
                jobs, rqjobs = ActionManageMixin.add(
                    action_class=NewSupportingInstructorAction,
                    logger=logger,
                    scheduler=scheduler,
                    triggers=Trigger.objects.filter(
                        active=True, action="new-supporting-instructor"),
                    context_objects=objs,
                    object_=task,
                    request=request,
                )
                jobs_created += jobs
                rqjobs_created += rqjobs

    return persons_created, tasks_created
Esempio n. 13
0
 def save(self, *args, **kwargs):
     # No self friendships!
     if self.source == self.target:
         raise IntegrityError('inviting and invited can not be the same')
     super().save(*args, **kwargs)
Esempio n. 14
0
 def clean(self):
     if not self.name:
         raise IntegrityError("The Cell name cannot be empty.")
Esempio n. 15
0
def parse_questions(file, course_users, all_topics, host):
    host = merge_url_parts([_format(host), _format("static")])
    distractors = []

    with open(file) as data_file:
        data = json.load(data_file)

    questions = data["questions"]
    counter = 0
    for q in questions:
        try:
            with transaction.atomic():
                distractor_count = 0
                counter = counter + 1
                if q["explanation"]["content"] is None:
                    q["explanation"]["content"] = " "

                question = Question(content=q["question"]["content"],
                                    explanation=q["explanation"]["content"],
                                    difficulty=randrange(0, 5),
                                    quality=randrange(0, 5),
                                    difficultyCount=randrange(0, 100),
                                    qualityCount=randrange(0, 100),
                                    author=choice(course_users))
                question.save()
                d = decode_images(question.id, question,
                                  q["question"]["payloads"], "q", host)
                if not d:
                    raise IntegrityError("Invalid Question Image")
                d = decode_images(question.id, question,
                                  q["explanation"]["payloads"], "e", host)
                if not d:
                    raise IntegrityError("Invalid Explanation Image")

                q_topics = q["topics"]
                for topic in q_topics:
                    idx = 0
                    while idx < len(all_topics):
                        if topic["name"] == all_topics[idx].name:
                            break
                        idx += 1
                    question.topics.add(all_topics[idx])
                question.save()

                _response_choices = ["A", "B", "C", "D"]
                if True not in [
                        q["responses"][i].get("isCorrect", False)
                        for i in _response_choices
                ]:
                    raise IntegrityError("No correct answer for question")

                for i in _response_choices:
                    response = q["responses"][i]
                    if response["content"] is None:
                        response["content"] = " "
                    distractor = Distractor(content=response["content"],
                                            response=i,
                                            isCorrect=response["isCorrect"],
                                            question=question)
                    distractor.save()
                    distractor_count += 1
                    d = decode_images(distractor.id, distractor,
                                      response["payloads"], "d", host)
                    if not d:
                        raise IntegrityError("Invalid Distractor Image")
                    distractors.append(distractor)
        except IntegrityError as e:
            distractors = distractors[:len(distractors) - distractor_count]
            print("Invalid question: " + str(counter))

    return distractors
Esempio n. 16
0
 def delete(self, *args, **kwargs):
     if self.start_year < 2015:
         raise IntegrityError(
             _('Prohibition to delete a learning unit before 2015.'))
     return super().delete(*args, **kwargs)
Esempio n. 17
0
def delete_group_from_stormpath(sender, instance, **kwargs):
    try:
        APPLICATION.groups.search({'name': instance.name})[0].delete()
    except StormpathError as e:
        raise IntegrityError(e)
Esempio n. 18
0
 def test_is_integrity_error(self):
     self.assertTrue(DjangoStorage.is_integrity_error(IntegrityError()))
Esempio n. 19
0
 def check_in(self):
     if self.checked_in:
         raise IntegrityError("attendee is already checked in")
     self.checked_in = timezone.now()
Esempio n. 20
0
 def save(self, *args, **kwargs):
     model = self.__class__
     if (model.objects.count() > 0 and self.pk != model.objects.get().pk):
         raise IntegrityError('Can only create 1 %s instance' % model.__name__)
     super(SingleInstanceMixin, self).save(*args, **kwargs)
Esempio n. 21
0
    def authenticate(self, **credentials):
        """
        Handles authentication of a user from the given credentials.
        Credentials must be a combination of 'request' and 'google_user'.
        If any other combination of credentials are given then we raise a TypeError, see
        authenticate() in django.contrib.auth.__init__.py.
        """

        User = get_user_model()

        if not issubclass(User, GaeAbstractBaseUser):
            raise ImproperlyConfigured(
                "djangae.contrib.auth.backends.AppEngineUserAPI requires AUTH_USER_MODEL to be a "
                " subclass of djangae.contrib.auth.base.GaeAbstractBaseUser.")

        if len(credentials) != 1:
            # Django expects a TypeError if this backend cannot handle the given credentials
            raise TypeError()

        google_user = credentials.get('google_user', None)

        if google_user:
            user_id = google_user.user_id()
            email = google_user.email().lower()
            try:
                return User.objects.get(username=user_id)
            except User.DoesNotExist:
                try:
                    existing_user = User.objects.get(
                        email=BaseUserManager.normalize_email(email))
                except User.DoesNotExist:
                    return User.objects.create_user(user_id, email)

                # If the existing user was precreated, update and reuse it
                if existing_user.username is None:
                    if (getattr(settings, 'DJANGAE_ALLOW_USER_PRE_CREATION',
                                False) or
                            # Backwards compatibility, remove before 1.0
                            getattr(settings, 'ALLOW_USER_PRE_CREATION',
                                    False)):
                        # Convert the pre-created User object so that the user can now login via
                        # Google Accounts, and ONLY via Google Accounts.
                        existing_user.username = user_id
                        existing_user.last_login = timezone.now()
                        existing_user.save()
                        return existing_user

                    # There's a precreated user but user precreation is disabled
                    # This will fail with an integrity error
                    from django.db import IntegrityError
                    raise IntegrityError(
                        "GAUTH: Found existing User with email=%s and username=None, "
                        "but user precreation is disabled." % email)

                # There is an existing user with this email address, but it is tied to a different
                # Google user id.  As we treat the user id as the primary identifier, not the email
                # address, we leave the existing user in place and blank its email address (as the
                # email field is unique), then create a new user with the new user id.
                else:
                    logging.info(
                        "GAUTH: Creating a new user with an existing email address "
                        "(User(email=%s, pk=%s))" % (email, existing_user.pk))
                    with self.atomic(**self.atomic_kwargs):
                        existing_user = User.objects.get(pk=existing_user.pk)
                        existing_user.email = None
                        existing_user.save()
                        return User.objects.create_user(user_id, email)
        else:
            raise TypeError(
            )  # Django expects to be able to pass in whatever credentials it has, and for you to raise a TypeError if they mean nothing to you
Esempio n. 22
0
def create_uploaded_persons_tasks(data):
    """
    Create persons and tasks from upload data.
    """

    # Quick sanity check.
    if any([row.get('errors') for row in data]):
        raise InternalError('Uploaded data contains errors, cancelling upload')

    persons_created = []
    tasks_created = []
    events = set()

    with transaction.atomic():
        for row in data:
            try:
                row_repr = ('{personal} {family} {username} <{email}>, '
                            '{role} at {event}').format(**row)

                fields = {key: row[key] for key in Person.PERSON_UPLOAD_FIELDS}
                fields['username'] = row['username']

                if row['person_exists'] and row['existing_person_id']:
                    # we should use existing Person
                    p = Person.objects.get(pk=row['existing_person_id'])

                elif row['person_exists'] and not row['existing_person_id']:
                    # we should use existing Person
                    p = Person.objects.get(
                        personal=fields['personal'], family=fields['family'],
                        username=fields['username'], email=fields['email'],
                    )

                else:
                    # we should create a new Person without any email provided
                    p = Person(**fields)
                    p.save()
                    persons_created.append(p)

                if row['event'] and row['role']:
                    e = Event.objects.get(slug=row['event'])
                    r = Role.objects.get(name=row['role'])

                    # if the number of learners attending the event changed,
                    # we should update ``event.attendance``
                    if row['role'] == 'learner':
                        events.add(e)

                    t, created = Task.objects.get_or_create(person=p, event=e,
                                                            role=r)
                    if created:
                        tasks_created.append(t)

            except IntegrityError as e:
                raise IntegrityError('{0} (for "{1}")'.format(str(e),
                                                              row_repr))

            except ObjectDoesNotExist as e:
                raise ObjectDoesNotExist('{0} (for "{1}")'.format(str(e),
                                                                  row_repr))

    return persons_created, tasks_created
Esempio n. 23
0
 def test_raises_error_creating_integration_feature(self, mock_create, mock_log):
     mock_create.side_effect = IntegrityError()
     self.creator.call()
     mock_log.assert_called_with(sentry_app="nulldb", error_message="")
Esempio n. 24
0
 def save(self, *args, **kwargs):
     if self.step <= 0:
         raise IntegrityError("Step must be > 0")
     super(RegularTimeSeries, self).save(*args, **kwargs)
 def delete(self, *args, **kwargs):
     # Disallow deleting a range with any dependents
     if self.benefit_set.exists() or self.condition_set.exists():
         raise IntegrityError(_('Can not delete range with a dependent benefit or condition.'))
     return super().delete(*args, **kwargs)
Esempio n. 26
0
 def assertSize(self):
     if len(self.timestamp) != len(self):
         raise IntegrityError("Timestamp and data not equally long")
Esempio n. 27
0
    def save(self, userprofile, commit=True):
        if commit is False:
            raise IntegrityError(
                'Saving logic complicated, commit must be enabled')
        if userprofile.is_member():
            raise IntegrityError('Model is already MemberProfile')
        # 1. clone profile
        uniqname = userprofile.uniqname
        marysuec = userprofile
        marysuec_user = userprofile.user
        marysuec_user.username = '******'
        marysuec_user.id = None
        marysuec_user.pk = None
        marysuec_user.save()
        marysuec.user = marysuec_user
        # 2. change uniqname to marysuec
        marysuec.uniqname = 'marysuec'
        marysuec.save()
        userprofile = UserProfile.objects.get(uniqname=uniqname)
        # 3. reassign all relationships of interest from profile A to marysuec
        nepp = userprofile.noneventprojectparticipant_set.all().distinct()
        shifts = userprofile.event_attendee.all().distinct()
        announcement_blurbs = userprofile.announcementblurb_set.all().distinct(
        )
        waitlist_slot = userprofile.waitlistslot_set.all().distinct()
        itembring = userprofile.usercanbringpreferreditem_set.all().distinct()
        praise_giver = userprofile.praise_giver.all().distinct()
        praise_receiver = userprofile.praise_recipient.all().distinct()
        prefs = userprofile.userpreference_set.all().distinct()
        background_check = userprofile.backgroundcheck_set.all().distinct()

        for n in nepp:
            n.participant = marysuec
            n.save()

        for s in shifts:
            s.attendees.add(marysuec)
            s.attendees.remove(userprofile)

        for a in announcement_blurbs:
            a.contacts.add(marysuec)
            a.contacts.remove(userprofile)

        for w in waitlist_slot:
            w.user = marysuec
            w.save()

        for item in itembring:
            item.user = marysuec
            item.save()

        for p in praise_giver:
            p.giver = marysuec
            p.save()

        for p in praise_receiver:
            p.recipient = marysuec
            p.save()

        for p in prefs:
            p.user = marysuec
            p.save()

        for b in background_check:
            b.member = marysuec
            b.save()

        # 4. delete profile A
        userprofile.delete()

        # 5. create profile A'
        m = super(ConvertNonMemberToMemberForm, self).save(commit=False)
        m.uniqname = uniqname
        m.user = User.objects.get(username=uniqname)
        m.nickname = marysuec.nickname
        m.first_name = marysuec.first_name
        m.middle_name = marysuec.middle_name
        m.last_name = marysuec.last_name
        m.suffix = marysuec.suffix
        m.maiden_name = marysuec.maiden_name
        m.title = marysuec.title
        # 6. save profile A'
        m.save()

        # 7. reassign all relationships from profile marysuec to A'
        for n in nepp:
            n.participant = m
            n.save()

        for s in shifts:
            s.attendees.add(m)
            s.attendees.remove(marysuec)

        for a in announcement_blurbs:
            a.contacts.add(m)
            a.contacts.remove(marysuec)

        for w in waitlist_slot:
            w.user = m
            w.save()

        for item in itembring:
            item.user = m
            item.save()

        for p in praise_giver:
            p.giver = m
            p.save()

        for p in praise_receiver:
            p.recipient = m
            p.save()

        for p in prefs:
            p.user = m
            p.save()

        for b in background_check:
            b.member = m
            b.save()

        # 8. delete marysuec
        marysuec.delete()
        marysuec_user.delete()
Esempio n. 28
0
 def save(self, *args, **kwargs):
     if self.date_from > self.date_to:
         raise IntegrityError('date_from must be less, than date_to')
     if self.status == mch.STATUS_CONFIRMED:
         self.subtract_day_off()
     super().save(*args, **kwargs)
Esempio n. 29
0
 def check_constraints(self, table_names=None):
     """
     Check each table name in `table_names` for rows with invalid foreign
     key references. This method is intended to be used in conjunction with
     `disable_constraint_checking()` and `enable_constraint_checking()`, to
     determine if rows with invalid references were entered while constraint
     checks were off.
     """
     if self.features.supports_pragma_foreign_key_check:
         with self.cursor() as cursor:
             if table_names is None:
                 violations = cursor.execute('PRAGMA foreign_key_check').fetchall()
             else:
                 violations = chain.from_iterable(
                     cursor.execute(
                         'PRAGMA foreign_key_check(%s)'
                         % self.ops.quote_name(table_name)
                     ).fetchall()
                     for table_name in table_names
                 )
             # See https://www.sqlite.org/pragma.html#pragma_foreign_key_check
             for table_name, rowid, referenced_table_name, foreign_key_index in violations:
                 foreign_key = cursor.execute(
                     'PRAGMA foreign_key_list(%s)' % self.ops.quote_name(table_name)
                 ).fetchall()[foreign_key_index]
                 column_name, referenced_column_name = foreign_key[3:5]
                 primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
                 primary_key_value, bad_value = cursor.execute(
                     'SELECT %s, %s FROM %s WHERE rowid = %%s' % (
                         self.ops.quote_name(primary_key_column_name),
                         self.ops.quote_name(column_name),
                         self.ops.quote_name(table_name),
                     ),
                     (rowid,),
                 ).fetchone()
                 raise IntegrityError(
                     "The row in table '%s' with primary key '%s' has an "
                     "invalid foreign key: %s.%s contains a value '%s' that "
                     "does not have a corresponding value in %s.%s." % (
                         table_name, primary_key_value, table_name, column_name,
                         bad_value, referenced_table_name, referenced_column_name
                     )
                 )
     else:
         with self.cursor() as cursor:
             if table_names is None:
                 table_names = self.introspection.table_names(cursor)
             for table_name in table_names:
                 primary_key_column_name = self.introspection.get_primary_key_column(cursor, table_name)
                 if not primary_key_column_name:
                     continue
                 key_columns = self.introspection.get_key_columns(cursor, table_name)
                 for column_name, referenced_table_name, referenced_column_name in key_columns:
                     cursor.execute(
                         """
                         SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING
                         LEFT JOIN `%s` as REFERRED
                         ON (REFERRING.`%s` = REFERRED.`%s`)
                         WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL
                         """
                         % (
                             primary_key_column_name, column_name, table_name,
                             referenced_table_name, column_name, referenced_column_name,
                             column_name, referenced_column_name,
                         )
                     )
                     for bad_row in cursor.fetchall():
                         raise IntegrityError(
                             "The row in table '%s' with primary key '%s' has an "
                             "invalid foreign key: %s.%s contains a value '%s' that "
                             "does not have a corresponding value in %s.%s." % (
                                 table_name, bad_row[0], table_name, column_name,
                                 bad_row[1], referenced_table_name, referenced_column_name,
                             )
                         )
Esempio n. 30
0
    def post(self, request):
        logger = logging.getLogger('netbox.views.BulkCreateView')
        model = self.queryset.model
        form = self.form(request.POST)
        model_form = self.model_form(request.POST)

        if form.is_valid():
            logger.debug("Form validation was successful")
            pattern = form.cleaned_data['pattern']
            new_objs = []

            try:
                with transaction.atomic():

                    # Create objects from the expanded. Abort the transaction on the first validation error.
                    for value in pattern:

                        # Reinstantiate the model form each time to avoid overwriting the same instance. Use a mutable
                        # copy of the POST QueryDict so that we can update the target field value.
                        model_form = self.model_form(request.POST.copy())
                        model_form.data[self.pattern_target] = value

                        # Validate each new object independently.
                        if model_form.is_valid():
                            obj = model_form.save()
                            logger.debug(f"Created {obj} (PK: {obj.pk})")
                            new_objs.append(obj)
                        else:
                            # Copy any errors on the pattern target field to the pattern form.
                            errors = model_form.errors.as_data()
                            if errors.get(self.pattern_target):
                                form.add_error('pattern', errors[self.pattern_target])
                            # Raise an IntegrityError to break the for loop and abort the transaction.
                            raise IntegrityError()

                    # Enforce object-level permissions
                    if self.queryset.filter(pk__in=[obj.pk for obj in new_objs]).count() != len(new_objs):
                        raise ObjectDoesNotExist

                    # If we make it to this point, validation has succeeded on all new objects.
                    msg = "Added {} {}".format(len(new_objs), model._meta.verbose_name_plural)
                    logger.info(msg)
                    messages.success(request, msg)

                    if '_addanother' in request.POST:
                        return redirect(request.path)
                    return redirect(self.get_return_url(request))

            except IntegrityError:
                pass

            except ObjectDoesNotExist:
                msg = "Object creation failed due to object-level permissions violation"
                logger.debug(msg)
                form.add_error(None, msg)

        else:
            logger.debug("Form validation failed")

        return render(request, self.template_name, {
            'form': form,
            'model_form': model_form,
            'obj_type': model._meta.verbose_name,
            'return_url': self.get_return_url(request),
        })